zoukankan      html  css  js  c++  java
  • 【题解】P1850 换教室

    题目

    洛谷 P1850 换教室

    思路

    期望dp。不会参考的ViXbob的题解
    (dp[i][j][0/1]) 为前 (i) 节课,申请调了 (j) 节课的最小期望,第三维的 (0) 表示第 (i) 节课不申请调,(1) 表示申请调。

    (a[i]) 表示第 (i) 节课原本的上课场所,(b[i]) 表示第 (i) 节课调整之后的上课场所。(dis[i][j]) 表示教室 (i) 到教室 (j) 的最短路径长度。

    (dp[i][j][0]=minegin{cases} dp[i-1][j][0]+dis[a[i-1]][a[i]] \[2ex] dp[i-1][j][1]+dis[b[i-1]][a[i]] * k[i-1]+dis[a[i-1]][a[i]] * (1-k[i-1])end{cases})

    (dp[i-1][j][0] + dis[a[i-1]][a[i]]) 表示前 (i-1) 节课,申请调了 (j) 节课且第 (i-1) 节课没有申请调的最优情况加上 (dis[a[i-1]][a[i]]) ,因为第 (i) 节课不申请调所以第 (i) 节课还是在 (a[i]) 上,(a[i-1]) 同理。

    (dp[i-1][j][1]+dis[b[i-1]][a[i]] * k[i-1] + dis[a[i-1]][a[i]] * (1-k[i-1])) 表示前 (i-1) 节课,调了 (j) 节课且第 (i-1) 节课申请调了的最优情况加上 (dis[b[i-1]][a[i]] * k[i-1])(申请调,并且通过的期望)再加上 (dis[a[i-1]][a[i]] * (1-k[i-1]))(申请调,但是没通过的期望)。

    (dp[i][j][1]=minegin{cases} dp[i-1][j-1][0]+dis[a[i-1]][a[i]]*(1-k[i])+dis[a[i-1]][b[i]]*k[i] \[2ex] dp[i-1][j-i][1]+dis[a[i-1]][a[i]]*(1-k[i-1])*(1-k[i])+dis[a[i-1]][b[i]]*(1-k[i-1])*k[i]+dis[b[i-1]][a[i]]*k[i-1]*(1-k[i])+dis[b[i-1]][b[i]]*k[i-1]*k[i] end{cases})

    (dp[i][j][1]) 的状态转移方程与 (dp[i][j][0]) 类似,不讲了(我懒)。

    跑 v 遍堆优化 Dijkstra 慢死了,不开 O2 过不了(可能是我写的太丑了/kk),Floyd 跑的快点。

    Code

    #include<cstdio>
    #include<cstring>
    #include<string>
    #include<iostream>
    #include<algorithm>
    #include<queue>
    #define MAXN 2001
    #define inf 2147483647
    
    inline void read(int &T) {
    	int x=0;bool f=0;char c=getchar();
    	while(c<'0'||c>'9'){if(c=='-')f=!f;c=getchar();}
    	while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
    	T=f?-x:x;
    }
    
    typedef std::pair<int,int> pii;
    std::priority_queue<pii,std::vector<pii>,std::greater<pii> >q;
    int n,m,v,e,pthn,head[301],a[MAXN],b[MAXN],dis[301][301];
    double ans=inf*114514.0,k[MAXN],dp[MAXN][MAXN][2];
    bool vis[301];
    struct Edge {
    	int next,to,w;
    }pth[90001<<1];
    
    void add(int from,int to,int w) {
    	pth[++pthn].to=to,pth[pthn].next=head[from];
    	pth[pthn].w=w,head[from]=pthn;
    }
    
    double min(double a,double b) {
    	return a<b?a:b;
    }
    
    void dij(int s) {
    	memset(vis,0,sizeof vis);
    	for(int i=0;i<=v;++i) dis[s][i]=inf;
    	dis[s][s]=0;
    	q.push(std::make_pair(dis[s][s],s));
    	while(!q.empty()) {
    		pii u=q.top();q.pop();
    		if(vis[u.second]) continue;
    		vis[u.second]=1;
    		for(int i=head[u.second];i;i=pth[i].next) {
    			int x=pth[i].to;
    			if(!vis[x]&&dis[s][x]>u.first+pth[i].w) {
    				dis[s][x]=dis[s][u.second]+pth[i].w;
    				q.push(std::make_pair(dis[s][x],x));
    			}
    		}
    	}
    }
    
    int main() {
    	read(n),read(m),read(v),read(e);
    	for(int i=1;i<=n;++i) read(a[i]);
    	for(int i=1;i<=n;++i) read(b[i]);
    	for(int i=1;i<=n;++i) scanf("%lf",&k[i]);
    	for(int i=1,x,y,w;i<=e;++i) {
    		read(x),read(y),read(w);
    		add(x,y,w),add(y,x,w);
    	}
    	for(int i=1;i<=v;++i) dij(i);
    	for(int i=1;i<=v;++i) dis[0][i]=dis[i][0]=0;
    	for(int i=0;i<=n;++i) {
    		for(int j=0;j<=m;++j) {
    			dp[i][j][0]=dp[i][j][1]=inf*114514.0;
    		}
    	}
    	dp[1][0][0]=dp[1][1][1]=0;
    	for(int i=2;i<=n;++i) {
    		dp[i][0][0]=dp[i-1][0][0]+dis[a[i-1]][a[i]];
    		for(int j=1;j<=min(i,m);++j) {
    			dp[i][j][0]=min(dp[i][j][0],min(dp[i-1][j][0]+dis[a[i-1]][a[i]],dp[i-1][j][1]+dis[b[i-1]][a[i]]*k[i-1]+dis[a[i-1]][a[i]]*(1-k[i-1])));
    			dp[i][j][1]=min(dp[i][j][1],min(dp[i-1][j-1][0]+dis[a[i-1]][b[i]]*k[i]+dis[a[i-1]][a[i]]*(1-k[i]),dp[i-1][j-1][1]+dis[b[i-1]][b[i]]*k[i]*k[i-1]+dis[b[i-1]][a[i]]*(1-k[i])*k[i-1]+dis[a[i-1]][b[i]]*(1-k[i-1])*k[i]+dis[a[i-1]][a[i]]*(1-k[i-1])*(1-k[i])));
    		}
    	}
    	for(int i=0;i<=m;++i) ans=min(ans,min(dp[n][i][0],dp[n][i][1]));
    	printf("%.2lf
    ",ans);
    	return 0;
    }
    
  • 相关阅读:
    java 装饰者模式与继承的区别
    Java学习笔记-多线程-创建线程的方式
    java IO流复制图片
    如何解决代码重复问题
    jdbc的基本应用
    java多线程
    java中的集合和数组
    Collections的应用
    Map集合的应用及其遍历方式
    qweb
  • 原文地址:https://www.cnblogs.com/poi-bolg-poi/p/12838667.html
Copyright © 2011-2022 走看看