[NOIp2016提高组]换教室

题目大意:
  有n节课,第i节课在c[i]上课,同时d[i]也有一节课d[i]。
  你有权利向教务处发出m次申请把自己的教室改到d[i],相应的批准概率是k[i]。
  教室是图上的一些点,其中每条边都有边权。
  问你上完所有课走的总路程的期望。

思路:
  动态规划。
  f[i][j][0/1]表示上了i个课,换了j次教室,这门课有没有换教室。
  转移方程为:
  f[i][j][0]=min(f[i-1][j][0]+dis[c[i-1]][c[i]],f[i-1][j][1]+dis[c[i-1]][c[i]]*(1-k[i-1])+dis[d[i-1]][c[i]]*k[i-1]);
  f[i][j][1]=min(f[i-1][j-1][0]+dis[c[i-1]][d[i]]*k[i]+dis[c[i-1]][c[i]]*(1-k[i]),f[i-1][j-1][1]+dis[d[i-1]][d[i]]*k[i-1]*k[i]+dis[d[i-1]][c[i]]*k[i-1]*(1-k[i])+dis[c[i-1]][d[i]]*(1-k[i-1])*k[i]+dis[c[i-1]][c[i]]*(1-k[i-1])*(1-k[i]));

 1 #include<cstdio>
 2 #include<cctype>
 3 #include<algorithm>
 4 inline int getint() {
 5     register char ch;
 6     while(!isdigit(ch=getchar()));
 7     register int x=ch^'0';
 8     while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0');
 9     return x;
10 }
11 const int inf=0x7fffffff;
12 const int N=2000,M=2001,V=301;
13 int c[N],d[N],dis[V][V];
14 double k[N],f[2][M][2];
15 int main() {
16     int n=getint(),m=getint(),v=getint(),e=getint();
17     for(register int i=0;i<n;i++) c[i]=getint();
18     for(register int i=0;i<n;i++) d[i]=getint();
19     for(register int i=0;i<n;i++) scanf("%lf",&k[i]);
20     for(register int i=1;i<=v;i++) {
21         for(register int j=1;j<=v;j++) {
22             if(i!=j) dis[i][j]=inf;
23         }
24     }
25     for(register int i=0;i<e;i++) {
26         const int u=getint(),v=getint(),w=getint();
27         dis[u][v]=dis[v][u]=std::min(dis[u][v],w);
28     }
29     for(register int k=1;k<=v;k++) {
30         for(register int i=1;i<=v;i++) {
31             if(dis[i][k]==inf) continue;
32             for(register int j=1;j<=v;j++) {
33                 if(dis[k][j]==inf) continue;
34                 dis[i][j]=std::min(dis[i][j],dis[i][k]+dis[k][j]);
35             }
36         }
37     }
38     for(register int j=0;j<=m;j++) {
39         f[0][j][0]=f[0][j][1]=1e9;
40     }
41     f[0][0][0]=f[0][1][1]=0;
42     for(register int i=1;i<n;i++) {
43         for(register int j=0;j<=m;j++) {
44             f[i&1][j][0]=f[i&1][j][1]=1e9;
45         }
46         f[i&1][0][0]=std::min(f[!(i&1)][0][0]+dis[c[i-1]][c[i]],f[!(i&1)][0][1]+dis[c[i-1]][c[i]]*(1-k[i-1])+dis[d[i-1]][c[i]]*k[i-1]);
47         for(register int j=1;j<=m;j++) {
48             f[i&1][j][0]=std::min(f[!(i&1)][j][0]+dis[c[i-1]][c[i]],f[!(i&1)][j][1]+dis[c[i-1]][c[i]]*(1-k[i-1])+dis[d[i-1]][c[i]]*k[i-1]);
49             f[i&1][j][1]=std::min(f[!(i&1)][j-1][0]+dis[c[i-1]][d[i]]*k[i]+dis[c[i-1]][c[i]]*(1-k[i]),f[!(i&1)][j-1][1]+dis[d[i-1]][d[i]]*k[i-1]*k[i]+dis[d[i-1]][c[i]]*k[i-1]*(1-k[i])+dis[c[i-1]][d[i]]*(1-k[i-1])*k[i]+dis[c[i-1]][c[i]]*(1-k[i-1])*(1-k[i]));
50         }
51     }
52     double ans=1e9;
53     for(register int i=0;i<=m;i++) {
54         ans=std::min(ans,std::min(f[!(n&1)][i][0],f[!(n&1)][i][1]));
55     }
56     printf("%.2f\n",ans);
57     return 0;
58 }

 

posted @ 2017-11-04 13:53  skylee03  阅读(139)  评论(0编辑  收藏  举报