bzoj 4720: [Noip2016]換教室【期望dp】
阿新 • • 發佈:2018-09-05
zoj can 期望dp getchar [1] using main urn ||
狀壓dp,設f[i][j][0/1]為前i個時間段換了j間教室的期望體力消耗,轉移很好想(但是寫起來好長= =)
#include<iostream> #include<cstdio> using namespace std; const int N=2005; int n,m,v,e,c[N],d[N]; double k[N],f[N][N][2],ans=1e9,a[N][N],z; int read() { int r=0,f=1; char p=getchar(); while(p<‘0‘||p>‘9‘) { if(p==‘-‘) f=-1; p=getchar(); } while(p>=‘0‘&&p<=‘9‘) { r=r*10+p-48; p=getchar(); } return r*f; } int main() { n=read(),m=read(),v=read(),e=read(); for(int i=1;i<=n;i++) c[i]=read(); for(int i=1;i<=n;i++) d[i]=read(); 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++) a[i][j]=1e9; for(int i=1;i<=v;i++) a[i][i]=0; for(int i=1;i<=e;i++) { int x=read(),y=read(); scanf("%lf",&z); a[x][y]=a[y][x]=min(z,a[x][y]); } for(int q=1;q<=v;q++) for(int i=1;i<=v;i++) for(int j=1;j<=v;j++) if(a[i][j]>a[i][q]+a[q][j]) a[i][j]=a[i][q]+a[q][j]; for(int i=1;i<=n;i++) for(int j=0;j<=m;j++) f[i][j][0]=f[i][j][1]=1e9; f[1][0][0]=f[1][1][1]=0.0; for(int i=2;i<=n;i++) { f[i][0][0]=f[i-1][0][0]+a[c[i-1]][c[i]]; for(int j=1;j<=min(m,i);j++) { f[i][j][0]=min(f[i-1][j][0]+a[c[i-1]][c[i]],f[i-1][j][1]+k[i-1]*a[d[i-1]][c[i]]+(1.0-k[i-1])*a[c[i-1]][c[i]]); f[i][j][1]=min(f[i-1][j-1][0]+k[i]*a[c[i-1]][d[i]]+(1.0-k[i])*a[c[i-1]][c[i]],f[i-1][j-1][1]+k[i-1]*k[i]*a[d[i-1]][d[i]]+(1.0-k[i-1])*k[i]*a[c[i-1]][d[i]]+k[i-1]*(1.0-k[i])*a[d[i-1]][c[i]]+(1.0-k[i-1])*(1.0-k[i])*a[c[i-1]][c[i]]); } } for(int i=0;i<=m;i++) ans=min(ans,min(f[n][i][0],f[n][i][1])); printf("%.2f\n",ans); return 0; }
bzoj 4720: [Noip2016]換教室【期望dp】