【NOIP2016】换教室——期望dp
其实还是要比d1t2的天天爱跑步简单一些的,期望dp的话也没考多难,就是转移方程可能稍微长一点。
考场上yyl说打个爆搜都能拿七十多分,%%%。
点数<=300,先跑一边floyd预处理出两两之间最短距离。
f[i][j]表示前i个时间段用了j次申请,再开一维0和1表示i这个时间段是否进行申请(0不申请1申请),那么
x=f[i-1][j][0]+dis[ci[i]][ci[i-1]];
y=f[i-1][j][1]+ki[i-1]*dis[ci[i]][di[i-1]]+(1-ki[i-1])*dis[ci[i]][ci[i-1]];
f[i][j][0]=min(x,y).
而选择申请的状态转移方程就更长了:
x=f[i-1][j-1][0]+ki[i]*dis[ci[i-1]][di[i]]+(1-ki[i])*dis[ci[i-1]][ci[i]];//前一个时间段不申请的期望
y=f[i-1][j-1][1]+ki[i-1]*ki[i]*dis[di[i]][di[i-1]]+ki[i-1]*(1-ki[i])*dis[di[i-1]][ci[i]];//前一个时间段选择申请的期望
y+=(1-ki[i-1])*ki[i]*dis[ci[i-1]][di[i]]+(1-ki[i-1])*(1-ki[i])*dis[ci[i-1]][ci[i]];//太长了所以写成两段
f[i][j][1]=min(x,y);
最后答案就是min(f[n][0][0],min(f[n][i][0],f[n][i][1])(1<=i<=m))
代码:
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 #define mem(a,p) memset(a,p,sizeof(a)) 5 typedef double Cu; 6 const int N=2005; 7 int n,m,v,e; 8 int ci[N],di[N]; 9 Cu dis[305][305]; 10 Cu ki[N]; 11 int read(){ 12 int ans=0,f=1;char c=getchar(); 13 while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();} 14 while(c>='0'&&c<='9'){ans=ans*10+c-48;c=getchar();} 15 return ans*f; 16 } 17 Cu min(Cu x,Cu y){return x>y?y:x;} 18 Cu max(Cu x,Cu y){return x<y?y:x;} 19 void floyd(){ 20 for(int k=1;k<=v;k++) 21 for(int i=1;i<=v;i++) 22 for(int j=1;j<=v;j++) 23 dis[i][j]=min(dis[i][j],dis[i][k]+dis[k][j]); 24 } 25 Cu f[N][N][2]; 26 int mins(int x,int y){return x>y?y:x;} 27 int main(){ 28 n=read();m=read();v=read();e=read(); 29 for(int i=1;i<=n;i++)ci[i]=read(); 30 for(int j=1;j<=n;j++)di[j]=read(); 31 for(int i=1;i<=n;i++)scanf("%lf",&ki[i]); 32 mem(dis,127);for(int i=1;i<=v;i++)dis[i][i]=0; 33 for(int i=1,a,b,c;i<=e;i++){ 34 a=read();b=read();c=read(); 35 dis[a][b]=dis[b][a]=min(c,dis[a][b]); 36 } 37 floyd();mem(f,127); 38 f[1][0][0]=f[1][1][1]=0; 39 for(int i=2;i<=n;i++){ 40 for(int j=0;j<=mins(m,i);j++){ 41 Cu x,y; 42 x=f[i-1][j][0]+dis[ci[i]][ci[i-1]]; 43 y=f[i-1][j][1]+ki[i-1]*dis[ci[i]][di[i-1]]+(1-ki[i-1])*dis[ci[i]][ci[i-1]]; 44 f[i][j][0]=min(x,y); 45 x=ki[i]*dis[ci[i-1]][di[i]]+(1-ki[i])*dis[ci[i-1]][ci[i]]; 46 if(!j)continue; 47 x+=f[i-1][j-1][0]; 48 y=f[i-1][j-1][1]+ki[i-1]*ki[i]*dis[di[i]][di[i-1]]+ki[i-1]*(1-ki[i])*dis[di[i-1]][ci[i]]; 49 y+=(1-ki[i-1])*ki[i]*dis[ci[i-1]][di[i]]+(1-ki[i-1])*(1-ki[i])*dis[ci[i-1]][ci[i]]; 50 f[i][j][1]=min(x,y); 51 } 52 } 53 Cu mni=f[n][0][0]; 54 for(int i=1;i<=m;i++)mni=min(mni,min(f[n][i][0],f[n][i][1])); 55 printf("%.2f",mni); 56 return 0; 57 }