之前感受很難不會的題,如今隨便就作了呢 =w=ios
原題:ide
最初想法,f[i][j][k]表示第i節課,在第j個教室(j=1或0),用了k次機會spa
能想出這個狀態就說明對指望和決策的理解不夠。。。3d
把所在教室表示出來表面上看是表示出了狀態,可是實際上指望是有不肯定性的,若是把所在的點明確地表示出來就消除了這種不肯定性code
正確作法是用j=1或0表示是否選擇換,即用決策表示狀態blog
由於請求之間是相互獨立的,因此能夠直接用p[i]和p[i-1]來控制前後兩個教室ci
若是不懂控制的意思,能夠看以下詳解get
先考慮簡單的狀況,先後都不選string
那麼f[i][0][k]=min(f[i][0][k],f[i-1][0][k]+d[a[i][0]][a[i-1][0]]),其中d[i][j]表示i和j之間距離,a[i][0]表示原教室編號,a[i][1]表示換教室編號it
若是前邊選呢
f[i][0][k]=min(f[i][0][k],f[i-1][1][k]+d[a[i][0]][a[i-1][1]]*p[i-1]+d[a[i][0]][a[i-1][0]]*(1-p[i-1])),其中d[i][j]表示i和j之間的距離,p[i]表示第i節申請成功的機率
這裏就是所謂的用p[i-1]控制前邊的教室
爲何f[i-1][1][k]能直接加而不乘機率呢
注意到,這個公式原本應該是p[i-1]*(第i-1節在a[i][1]的指望值+d[a[i-1][1]][a[i][0]])+(1-p[i-1])*(第i-1節在a[i][0]的指望值+d[a[i-1][0]][a[i][0]])
而後咱們能夠發現p[i-1]*第i-1節在a[i][1]的指望值+(1-p[i-1])*第i-1節在a[i][0]的指望值正是第i-1節選擇申請的指望值
因此把這兩項合併,就獲得上述公式
這裏須要注意理清指望的意義
對於其餘兩種狀況同理
f[i][1][k]=min(f[i][1][k],f[i-1][0][k-1]+d[a[i][1]][a[i-1][0]]*p[i]+d[a[i][0]][a[i-1][0]]*(1-p[i]));
f[i][1][k]=min(f[i][1][k],f[i-1][1][k-1]
+d[a[i][1]][a[i-1][1]]*p[i]*p[i-1]
+d[a[i][1]][a[i-1][0]]*p[i]*(1-p[i-1])
+d[a[i][0]][a[i-1][1]]*(1-p[i])*p[i-1]
+d[a[i][0]][a[i-1][0]]*(1-p[i])*(1-p[i-1]));
還挺有規律的
代碼:
1 #include<iostream> 2 #include<cstdio> 3 #include<algorithm> 4 #include<cstring> 5 #include<cmath> 6 using namespace std; 7 const int oo=1000000007; 8 int rd(){int z=0,mk=1; char ch=getchar(); 9 while(ch<'0'||ch>'9'){if(ch=='-')mk=-1; ch=getchar();} 10 while(ch>='0'&&ch<='9'){z=(z<<3)+(z<<1)+ch-'0'; ch=getchar();} 11 return z*mk; 12 } 13 int n,o,m,c,a[2100][2]; 14 int e[310][310]; 15 double p[2100]; 16 double f[2100][2][2100]; 17 void flyd(){ 18 for(int k=1;k<=m;++k)for(int i=1;i<=m;++i)for(int j=1;j<=m;++j) 19 e[i][j]=min(e[i][j],e[i][k]+e[k][j]); 20 } 21 void prvs(){ 22 for(int i=1;i<=m;++i){ 23 e[i][i]=0; 24 for(int j=i+1;j<=m;++j) 25 e[i][j]=oo,e[j][i]=oo; 26 } 27 for(int i=1;i<=n;++i)for(int j=0;j<=1;++j) 28 for(int k=0;k<=o;++k) f[i][j][k]=oo; 29 } 30 int main(){ 31 //freopen("ddd.in","r",stdin); 32 cin>>n>>o>>m>>c; prvs(); 33 for(int i=1;i<=n;++i) a[i][0]=rd(); 34 for(int i=1;i<=n;++i) a[i][1]=rd(); 35 for(int i=1;i<=n;++i) scanf("%lf",&p[i]); 36 int l,r,mk; 37 while(c --> 0){ 38 l=rd(),r=rd(),mk=rd(); 39 e[l][r]=min(e[l][r],mk); 40 e[r][l]=min(e[r][l],mk); 41 } 42 flyd(); 43 f[1][0][0]=0,f[1][1][1]=0; 44 for(int i=2;i<=n;++i)for(int k=0;k<=o;++k){ 45 f[i][0][k]=min(f[i][0][k],f[i-1][0][k] 46 +e[a[i][0]][a[i-1][0]]); 47 f[i][0][k]=min(f[i][0][k],f[i-1][1][k] 48 +e[a[i][0]][a[i-1][1]]*p[i-1] 49 +e[a[i][0]][a[i-1][0]]*(1-p[i-1])); 50 if(k){ 51 f[i][1][k]=min(f[i][1][k],f[i-1][0][k-1] 52 +e[a[i][1]][a[i-1][0]]*p[i] 53 +e[a[i][0]][a[i-1][0]]*(1-p[i])); 54 f[i][1][k]=min(f[i][1][k],f[i-1][1][k-1] 55 +e[a[i][1]][a[i-1][1]]*p[i]*p[i-1] 56 +e[a[i][1]][a[i-1][0]]*p[i]*(1-p[i-1]) 57 +e[a[i][0]][a[i-1][1]]*(1-p[i])*p[i-1] 58 +e[a[i][0]][a[i-1][0]]*(1-p[i])*(1-p[i-1])); 59 } 60 } 61 double ans=oo; 62 for(int i=0;i<=o;++i){ 63 ans=min(ans,f[n][0][i]); 64 ans=min(ans,f[n][1][i]); 65 } 66 printf("%.2lf\n",ans); 67 return 0; 68 }