zoukankan      html  css  js  c++  java
  • 【uoj262】 NOIP2016—换教室

    http://uoj.ac/problem/262 (题目链接)

    题意

      有${n}$个时间段,第${i}$个时间段可以选择在${c_i}$教室上课,也可以选择申请换课,有${k_i}$概率申请通过,在${d_i}$上课,另外${1-k_i}$的概率留在${c_i}$教室。 总共有${v}$个教室,${e}$条路径双向联通教室${x_i}$和${y_i}$,路径有权值${w_i}$。在课间时(相邻两个时间段的间隔中),你要从上一个教室走最短路径到下一个教室。 现在你有${m}$次申请机会,只能提前申请一堆换课(也就是你不能在知道某一次申请结果后再去申请下一个换课)。求总距离的最小期望。

    Solution

      跟去年那道子串好像啊。。

      先floyd算出图中两两点之间的距离,然后dp。

      用${f[i][j]}$表示上到第${i}$堂课,已经申请了${j}$次,并且第${i}$堂课的教室被申请,所花费的总体力。

      用${g[i][j]}$表示上到第${i}$堂课,已经申请了${j}$次,并且第${i}$堂课的教室没有被申请,所花费的总体力。

      转移很显然$${f[i][j]=Min(f[i-1][j-1]+dis,g[i-1][j-1]+dis)}$$

      $${g[i][j]=Min(f[i-1][j]+dis,g[i-1][j]+dis)}$$

    细节

      注意Floyd的总点数是V(好像坑了好多人)。

    代码

    // uoj262
    #include<algorithm>
    #include<iostream>
    #include<cstring>
    #include<cstdlib>
    #include<cstdio>
    #include<cmath>
    #define inf 2147483640
    #define LL long long
    #define Pi acos(-1.0)
    #define free(a) freopen(a".in","r",stdin),freopen(a".out","w",stdout)
    using namespace std;
    
    const int maxn=2010;
    int n,m,E,V;
    int c[maxn],d[maxn];
    double dis[maxn][maxn],K[maxn],f[maxn][maxn],g[maxn][maxn];
    
    void Floyd() {
    	for (int k=1;k<=V;k++)
    		for (int i=1;i<=V;i++)
    			for (int j=1;j<=V;j++)
    				dis[i][j]=min(dis[i][j],dis[i][k]+dis[k][j]);
    }
    void dp() {
    	for (int i=1;i<=n;i++)
    		for (int j=0;j<=m;j++) f[i][j]=g[i][j]=inf;
    	g[1][0]=f[1][1]=0;
    	for (int i=2;i<=n;i++)
    		for (int j=0;j<=min(i,m);j++) {
    			if (j) {
    				f[i][j]=f[i-1][j-1]+K[i-1]*K[i]*dis[d[i-1]][d[i]];
    				f[i][j]+=K[i-1]*(1-K[i])*dis[d[i-1]][c[i]];
    				f[i][j]+=(1-K[i-1])*K[i]*dis[c[i-1]][d[i]];
    				f[i][j]+=(1-K[i-1])*(1-K[i])*dis[c[i-1]][c[i]];
    				f[i][j]=min(f[i][j],g[i-1][j-1]+K[i]*dis[c[i-1]][d[i]]+(1-K[i])*dis[c[i-1]][c[i]]);
    			}
    			g[i][j]=min(f[i-1][j]+K[i-1]*dis[d[i-1]][c[i]]+(1-K[i-1])*dis[c[i-1]][c[i]],g[i-1][j]+dis[c[i-1]][c[i]]);
    		}
    }
    int main() {
    	scanf("%d%d%d%d",&n,&m,&V,&E);
    	for (int i=1;i<=n;i++) scanf("%d",&c[i]);
    	for (int i=1;i<=n;i++) scanf("%d",&d[i]);
    	for (int i=1;i<=n;i++) scanf("%lf",&K[i]);
    	for (int i=1;i<=V;i++) {
    		for (int j=1;j<=V;j++) dis[i][j]=inf;
    		dis[i][i]=0;
    	}
    	for (int u,v,w,i=1;i<=E;i++) {
    		scanf("%d%d%d",&u,&v,&w);
    		dis[u][v]=min(dis[u][v],(double)w);
    		dis[v][u]=min(dis[v][u],(double)w);
    	}
    	Floyd();
    	dp();
    	double ans=inf;
    	for (int i=0;i<=m;i++) ans=min(ans,min(f[n][i],g[n][i]));
    	printf("%.2lf",ans);
    	return 0;
    }
    

      

  • 相关阅读:
    洛谷—— P1187 3D模型
    商铺项目(Redis缓存)
    商铺项目(使用DES加密配置信息)
    Linux下tomcat启动项目原因排查
    商铺项目(商品详情页开发)
    商铺项目(店铺详情页开发)
    商铺项目(店铺列表开发)
    商铺项目(首页前端开发)
    商铺项目(首页后台开发)
    商铺项目(商品类别模块二)
  • 原文地址:https://www.cnblogs.com/MashiroSky/p/6159305.html
Copyright © 2011-2022 走看看