题目:P1850 换教室
期望dp。
对于期望dp的套路就是大力分类讨论不同情况然后计算概率。
本题设:f[i][j]:在第i节课 换了j个教室
·现在要更换教室 :f[i][j][1]
·现在更换成功了
·上一次要更换教室
·上一次更换成功了 : f[i-1][j-1][1]+k[i]*k[i-1]*dis[d[i-1]][d[i]]
·上一次更换失败了 : f[i-1][j-1][0]+k[i]*(1-k[i-1])*dis[c[i-1]][d[i]]
·上一次不更换教室
·上一次更换失败了 : f[i-1][j][0]+k[i]*dis[c[i-1]][d[i]]
·现在更换失败了
·上一次要更换教室
·上一次更换成功了 : f[i-1][j-1][1]+k[i-1]*(1-k[i])*dis[d[i-1]][c[i]]
·上一次更换失败了 :f[i-1][j-1][0]+(1-k[i-1])*(1-k[i])*dis[c[i-1]][c[i]]
·上一次不更换教室
·上一次更换失败了 :f[i-1][j][0]+(1-k[i])*dis[c[i-1]][d[i]]
·现在不更换教室 : f[i][j][0]
·现在更换失败了
·上一次要更换教室
·上一次更换成功了 :f[i-1][j-1][1]+k[i-1]*dis[d[i-1]][c[i]]
·上一次更换失败了 :f[i-1][j-1][0]+(1-k[i-1])*dis[c[i-1]][c[i]]
·上一次不更换教室
·上一次更换失败了 :f[i-1][j][0]+dis[c[i-1]][c[i]]
接下来就是预处理最短路,Floyd很方便。还有就是m次不一定用完,最后在f[n][i][0/1](i∈m)里面求最小值。解决问题!
所以期望dp就是要有耐心地大力分类讨论!
1 #include<stdio.h> 2 #define it register int 3 #define il inline 4 #define Min(a,b) (a<b?a:b) 5 const int N=2005; 6 typedef double db; 7 int dis[N][N],c[N],d[N],n,m,q,e; 8 db k[N],f[N][N][2]; 9 il void fr(int &num){ 10 num=0;char c=getchar();int p=1; 11 while(c<'0'||c>'9') c=='-'?p=-1,c=getchar():c=getchar(); 12 while(c>='0'&&c<='9') num=num*10+c-'0',c=getchar(); 13 num*=p; 14 } 15 int main(){ 16 fr(n),fr(m),fr(q),fr(e); 17 for(it i=1;i<=n;++i) fr(c[i]); 18 for(it i=1;i<=n;++i) fr(d[i]); 19 for(it i=1;i<=n;++i) scanf("%lf",&k[i]); 20 for(it i=1;i<=q;++i){ 21 for(it j=1;j<=q;++j) dis[i][j]=1e9; 22 dis[i][i]=0; 23 } 24 for(it i=1,u,v,x;i<=e;++i) 25 fr(u),fr(v),fr(x),dis[u][v]=dis[v][u]=Min(dis[u][v],x); 26 for(it k=1;k<=q;++k) 27 for(it i=1;i<=q;++i) 28 for(it j=1;j<=q;++j) 29 dis[i][j]=Min(dis[i][j],dis[i][k]+dis[k][j]); 30 for(it i=1;i<=n;++i) 31 for(it j=0;j<=m;++j) 32 f[i][j][0]=f[i][j][1]=1e9; 33 f[1][0][0]=0,f[1][1][1]=0; 34 for(it i=2;i<=n;++i) 35 for(it j=0;j<=m;++j){ 36 f[i][j][0]=Min(f[i-1][j][1]+k[i-1]*dis[d[i-1]][c[i]]+(1-k[i-1])*dis[c[i-1]][c[i]],f[i-1][j][0]+dis[c[i-1]][c[i]]); 37 if(j) f[i][j][1]=Min(f[i-1][j-1][1]+k[i-1]*k[i]*dis[d[i-1]][d[i]]+k[i-1]*(1-k[i])*dis[d[i-1]][c[i]]+(1-k[i-1])*k[i]*dis[c[i-1]][d[i]]+(1-k[i-1])*(1-k[i])*dis[c[i-1]][c[i]],f[i-1][j-1][0]+k[i]*dis[c[i-1]][d[i]]+(1-k[i])*dis[c[i-1]][c[i]]); 38 } 39 db ans=1e9; 40 for(it i=0;i<=m;++i) 41 ans=Min(ans,Min(f[n][i][0],f[n][i][1])); 42 printf("%.2lf",ans); 43 return 0; 44 } 45 /* 46 f[i][j]:在第i节课 换了j个教室 47 ·现在要更换教室 :f[i][j][1] 48 ·现在更换成功了 49 ·上一次要更换教室 50 ·上一次更换成功了 : f[i-1][j-1][1]+k[i]*k[i-1]*dis[d[i-1]][d[i]] 51 ·上一次更换失败了 : f[i-1][j-1][0]+k[i]*(1-k[i-1])*dis[c[i-1]][d[i]] 52 ·上一次不更换教室 53 ·上一次更换失败了 : f[i-1][j][0]+k[i]*dis[c[i-1]][d[i]] 54 ·现在更换失败了 55 ·上一次要更换教室 56 ·上一次更换成功了 : f[i-1][j-1][1]+k[i-1]*(1-k[i])*dis[d[i-1]][c[i]] 57 ·上一次更换失败了 :f[i-1][j-1][0]+(1-k[i-1])*(1-k[i])*dis[c[i-1]][c[i]] 58 ·上一次不更换教室 59 ·上一次更换失败了 :f[i-1][j][0]+(1-k[i])*dis[c[i-1]][d[i]] 60 ·现在不更换教室 : f[i][j][0] 61 ·现在更换失败了 62 ·上一次要更换教室 63 ·上一次更换成功了 :f[i-1][j-1][1]+k[i-1]*dis[d[i-1]][c[i]] 64 ·上一次更换失败了 :f[i-1][j-1][0]+(1-k[i-1])*dis[c[i-1]][c[i]] 65 ·上一次不更换教室 66 ·上一次更换失败了 :f[i-1][j][0]+dis[c[i-1]][c[i]] 67 */