[NOIP2016]换教室

Posted Nawox

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[NOIP2016]换教室相关的知识,希望对你有一定的参考价值。

     这道题应该是一个概率dp

     首先先用floyd跑一遍处理处最短路,其中两点需要注意

           1、dis[i][i]要初始化为零

            2、注意有重边!!!!

    之后就开始dp转移,用f[i][j][k] 来表示状态,i 表示是i 时刻;j表示还剩下多少可以换教室的机会;当k=0表示在i时间点,剩下j的机会的情况下,不换教室,k=1表示换教室;

   所以f[i][j][0]=min(f[i-1][j][0]+dis[beg[i-1]][beg[i]],f[i-1][j][1]+dis[beg[i-1]][beg[i]]*(1-p[i-1])+dis[ano[i-1]][beg[i]]*p[i]),其中p[i]是i时刻换教室的成功概率,beg[i]是初始教室,ano[i]是可换的教室;

   f[i][j-1][0]=min(f[i-1][j][0]+(double)dis[beg[i-1]][beg[i]]*(1-p[i])+(double)dis[beg[i-1]][ano[i]]*p[i],

f[i-1][j][1]+(double)dis[beg[i-1]][beg[i]]*(1-p[i-1])*(1-p[i])+(double)dis[beg[i-1]][ano[i]]
*(1-p[i-1])*p[i]+(double)dis[ano[i-1]][beg[i]]*p[i-1]*(1-p[i])
+(double)dis[ano[i-1]][ano[i]]*p[i-1]*p[i])
转移方程有点长的,但总之就是在四个可行的道路之间选择,并乘上概率,就这么一直转移到n即可,在for循环找一遍答案就行了         
 1 #include<cmath>
 2 #include<cstdio>
 3 #include<cstdlib>
 4 #include<cstring>
 5 #include<iostream>
 6 #include<algorithm>
 7 using namespace std;
 8 int n,m,dian_shu,bian_shu;
 9 int beg[2010],ano[2010];
10 double p[2010];
11 int dis[310][310];
12 double f[2010][2010][3];
13 void ot(){
14     for(int i=1;i<=n;i++){
15         for(int j=0;j<=m;j++){
16             cout<<"ij= "<<i<<"  "<<j<<endl;
17             cout<<f[i][j][0]<<"   "<<f[i][j][1]<<endl;
18         }
19     }
20 }
21 void ot2(){
22     for(int i=0;i<=m;i++){
23         cout<<"i== "<<i<<endl;
24         cout<<"-- "<<f[2][i][0]<<"  "<<f[2][i][1]<<endl;
25     }
26 }
27 void init(){
28     for(int i=1;i<=n;i++) scanf("%d",&beg[i]);
29     for(int i=1;i<=n;i++) scanf("%d",&ano[i]);
30     for(int i=1;i<=n;i++) scanf("%lf",&p[i]);
31     int x,y,z;
32     memset(dis,30,sizeof(dis));
33     for(int i=1;i<=dian_shu;i++)
34         dis[i][i]=0;
35     for(int i=1;i<=bian_shu;i++){
36         scanf("%d%d%d",&x,&y,&z);
37         dis[x][y]=min(dis[x][y],z); dis[y][x]=min(dis[y][x],z);
38     }
39     for(int k=1;k<=dian_shu;k++){
40         for(int i=1;i<=dian_shu;i++){
41             for(int j=1;j<=dian_shu;j++){
42                 dis[i][j]=min(dis[i][j],dis[i][k]+dis[k][j]);
43             }
44         }
45     }
46 }
47 void Dp(){
48     for(int i=1;i<=n;i++){
49         for(int j=0;j<=m;j++){
50             f[i][j][1]=f[i][j][0]=200000000.0;
51         }
52     }
53     f[1][m][0]=0;
54     f[1][m-1][1]=0;
55     for(int i=2;i<=n;i++){
56         for(int j=m;j>=0;j--){
57             f[i][j][0]=min( f[i-1][j][0] + (double)dis[beg[i-1]][beg[i]] ,f[i-1][j][1] + (double)(1-p[i-1])*dis[beg[i-1]][beg[i]] + (double)p[i-1]*dis[ano[i-1]][beg[i]]);
58             if(j==0) continue;
59             double aa=f[i-1][j][0]+(double)dis[beg[i-1]][beg[i]]*(1-p[i])+(double)dis[beg[i-1]][ano[i]]*p[i];
60             double bb=f[i-1][j][1]+(double)dis[beg[i-1]][beg[i]]*(1-p[i-1])*(1-p[i])+(double)dis[beg[i-1]][ano[i]]*(1-p[i-1])*p[i]
61                       +(double)dis[ano[i-1]][beg[i]]*p[i-1]*(1-p[i])+(double)dis[ano[i-1]][ano[i]]*p[i-1]*p[i];
62             /*if(i==2 && j==1){
63                 cout<<(double)dis[ano[i-1]][ano[i]]*p[i-1]*p[i]<<endl;
64                 cout<<"-->   "<<aa<<"  "<<bb<<endl;
65             }*/
66             f[i][j-1][1]=min(aa,bb);
67         }
68     }
69 }
70 int main(){
71     //freopen("classrooma.in","r",stdin);
72     //freopen("classrooma.out","w",stdout);
73     scanf("%d%d%d%d",&n,&m,&dian_shu,&bian_shu);
74     init();
75     Dp();
76     double ans=200000000.0;
77     for(int i=0;i<=m;i++){
78         ans=min(ans,f[n][i][0]);
79         ans=min(ans,f[n][i][1]);
80     }
81     //ot();
82 //  ot2();
83 /*
84     int sc=0;
85     cout<<"st"<<endl;
86     for(int i=2;i<=n;i++){
87         sc+=dis[beg[i-1]][beg[i]];
88         cout<<dis[beg[i-1]][beg[i]]<<endl;
89     }
90     cout<<"sc== "<<sc<<endl;*/
91     printf("%.2lf",ans);
92     return 0;
93  
94 }
95 /**********************************************

 

以上是关于[NOIP2016]换教室的主要内容,如果未能解决你的问题,请参考以下文章

uoj262 NOIP2016—换教室

[NOIp2016提高组]换教室

noip 2016 换教室

[NOIP2016提高组]换教室

[NOIP2016]换教室 题解(奇怪的三种状态)

[NOIp 2016]换教室