[洛谷P1850][题解]换教室

题目戳此

一个比较毒瘤的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\n",ans);
83 }
84 int main(){
85     Initi();
86     Floyd();
87     DP();
88     Print();
89     return 0;
90 }

完结撒花~~~

posted @ 2020-02-21 19:47  ajthreac  阅读(136)  评论(1编辑  收藏  举报