一个比较毒瘤的DP题。
设f[i][j][1/0]为前i个时段、申请j次、第i个时段申请成功与否
思考下面几种情况:
一:i未申请f[i][j][0]
(1)i-1申请
1.i-1申请成功
2.i-1申请失败
(2)i-1未申请
二:i申请f[i][j][1]
(1)i-1申请
1.前后均成功
2.前成功后失败
3.前失败后成功
4.前后均失败
(2)i-1未申请
1.i申请成功
2.i申请失败
以上九种情况都体现在代码里了:
1 #include<bits/stdc++.h> 2 #define LL long long 3 #define rg register 4 #define us unsigned 5 #define eps 1e-6 6 #define INF 0x3f3f3f3f 7 #define ls k<<1 8 #define rs k<<1|1 9 #define tmid ((tr[k].l+tr[k].r)>>1) 10 #define nmid ((l+r)>>1) 11 #define Thispoint tr[k].l==tr[k].r 12 #define pushup tr[k].wei=tr[ls].wei+tr[rs].wei 13 using namespace std; 14 inline void Read(int &x){ 15 int f=1; 16 char c=getchar(); 17 x=0; 18 while(c<'0'||c>'9'){ 19 if(c=='-')f=-1; 20 c=getchar(); 21 } 22 while(c>='0'&&c<='9'){ 23 x=(x<<3)+(x<<1)+c-'0'; 24 c=getchar(); 25 } 26 x*=f; 27 } 28 int n,m,v,e; 29 int c[2010],d[2010],dis[310][310]; 30 double k[2010],f[2010][2010][2]; 31 inline void Initi(){ 32 Read(n),Read(m),Read(v),Read(e); 33 for(int i=1;i<=v;i++){ 34 for(int j=1;j<i;j++){ 35 dis[i][j]=dis[j][i]=INF; 36 } 37 } 38 for(int i=1;i<=n;i++)Read(c[i]); 39 for(int i=1;i<=n;i++)Read(d[i]); 40 for(int i=1;i<=n;i++)cin>>k[i]; 41 for(int i=1;i<=e;i++){ 42 int a,b,w; 43 Read(a),Read(b),Read(w); 44 dis[a][b]=min(dis[a][b],w); 45 dis[b][a]=dis[a][b]; 46 } 47 } 48 inline void Floyd(){ 49 for(int k=1;k<=v;k++){ 50 for(int i=1;i<=v;i++){ 51 for(int j=1;j<i;j++){ 52 if(dis[i][j]>dis[i][k]+dis[k][j]){ 53 dis[i][j]=dis[j][i]=dis[i][k]+dis[k][j]; 54 } 55 } 56 } 57 } 58 } 59 inline void DP(){ 60 for(int i=1;i<=n;i++){ 61 for(int j=0;j<=m;j++){ 62 f[i][j][0]=f[i][j][1]=INF; 63 } 64 } 65 f[1][0][0]=0; 66 f[1][1][1]=0; 67 for(int i=2;i<=n;i++){ 68 for(int j=0;j<=m;j++){ 69 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]]); 70 if(j!=0){ 71 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]]); 72 } 73 } 74 } 75 } 76 inline void Print(){ 77 double ans=INF; 78 for(int i=0;i<=m;i++){ 79 // cout<<f[n][i][0]<<" "<<f[n][i][1]<<endl; 80 ans=min(ans,min(f[n][i][0],f[n][i][1])); 81 } 82 printf("%.2lf ",ans); 83 } 84 int main(){ 85 Initi(); 86 Floyd(); 87 DP(); 88 Print(); 89 return 0; 90 }
完结撒花~~~