luogu1850 NOIP2016 换教室

题目

注:以上图片截图自洛谷

分析

 这道题概率DP,前置知识:数学期望

part 1 状态

dp [ 第 i 个时间段 ] [ 换了 j 次 ] [ 当前是否换了 ] = 最优方案的期望值

part 2 转移

我们把期望下放到每条路;

你可以选择申请或不申请;

如果选择申请:期望的路径长 = (申请成功的路径长) * 申请成功概率 + (申请不成功的路径长) * 申请不成功概率

这里注意不要被样例解释误导了,推导一下他们其实是一样的,因为我们的状态是:dp [ 第 i 个时间段 ] [ 换了 j 次 ] [ 当前是否换了 ] = 最优方案的期望值

代码

  1 /*************************
  2 User:Mandy.H.Y
  3 Language:c++
  4 Problem:luogu1850
  5 Algorithm: 
  6 *************************/
  7 
  8 #include<bits/stdc++.h>
  9 
 10 using namespace std;
 11 
 12 const int maxn = 2005;
 13 const int maxv = 305;
 14 const int maxe = 90005;
 15 
 16 int n,m,v,e,size;
 17 int c[maxn],d[maxn];
 18 double k[maxn],dp[maxn][maxn][3];
 19 int g[maxv][maxv];
 20 
 21 struct Edge{
 22     int v,nt,w;
 23 }edge[maxe << 1];
 24 
 25 template<class T>inline void read(T &x){
 26     x = 0;bool flag = 0;char ch = getchar();
 27     while(!isdigit(ch)) flag |= ch == '-',ch = getchar();
 28     while(isdigit(ch)) x = (x << 1) + (x << 3) + (ch ^ 48),ch = getchar();
 29     if(flag) x = -x;
 30 }
 31 
 32 template<class T>void putch(const T x){
 33     if(x > 9) putch(x / 10);
 34     putchar(x % 10 | 48);
 35 }
 36 
 37 template<class T>void put(const T x){
 38     if(x < 0) putchar('-'),putch(-x);
 39     else putch(x);
 40 }
 41 
 42 void file(){
 43     freopen("1850.in","r",stdin);
 44     freopen("1850.out","w",stdout);
 45 }
 46 
 47 void readdata(){
 48     memset(g,0x3f3f3f3f,sizeof(g));
 49     read(n);read(m);read(v);read(e);
 50     for(int i = 1;i <= v; ++ i) g[i][i] = 0;
 51     for(int i = 1;i <= n; ++ i) read(c[i]);
 52     for(int i = 1;i <= n; ++ i) read(d[i]);
 53     for(int i = 1;i <= n; ++ i) scanf("%lf",&k[i]);
 54     for(int i = 1;i <= e; ++ i) {
 55         int u,v,w;
 56         read(u);read(v);read(w);
 57         g[u][v] = min(g[u][v],w);
 58         g[v][u] = g[u][v];
 59     }
 60 }
 61 
 62 void Floyd(){
 63     for(int l = 1;l <= v; ++ l)
 64     for(int i = 1;i <= v; ++ i)
 65     for(int j = 1;j <= v; ++ j){
 66         if(g[i][l] != 0x3f3f3f3f && g[l][j] != 0x3f3f3f3f)
 67             if(g[i][l] + g[l][j] < g[i][j]) g[i][j] = g[i][l] + g[l][j];
 68     }
 69 }
 70 
 71 void work(){
 72     
 73     Floyd();
 74     
 75     for(int i = 2;i <= n; ++ i){
 76         
 77         int u1 = c[i - 1],u2 = d[i - 1];
 78         int v1 = c[i],v2 = d[i];
 79         
 80         dp[i][0][0] = dp[i - 1][0][0] + g[u1][v1];
 81         
 82         for(int j = 1;j <= m; ++ j){
 83             
 84             dp[i][j][0] = min(dp[i - 1][j][0] + g[u1][v1],
 85                               dp[i - 1][j][1] + 
 86                               k[i - 1] * g[u2][v1] + 
 87                               (1 - k[i - 1]) * g[u1][v1]);
 88             
 89             dp[i][j][1] = dp[i - 1][j - 1][0] + 
 90                           k[i] * g[u1][v2] + 
 91                           (1 - k[i]) * g[u1][v1];
 92             if(j > 1) dp[i][j][1] = min(dp[i][j][1],dp[i - 1][j - 1][1] + 
 93                                                     k[i - 1] * k[i] * g[u2][v2] + 
 94                                                     k[i - 1] * (1 - k[i]) * g[u2][v1] +
 95                                                     (1 - k[i - 1]) * k[i] * g[u1][v2] +
 96                                                     (1 - k[i - 1]) * (1 - k[i]) * g[u1][v1]);
 97         
 98         }
 99     }
100     double ans = 2000000000.0;
101     for(int i = 0;i <= m; ++ i) {
102         ans = min(ans,dp[n][i][0]);
103         if(i > 0) ans = min(ans,dp[n][i][1]);
104     }
105     
106     printf("%.2lf",ans);
107 }
108 
109 int main(){
110 //    file();
111     readdata();
112     work();
113     return 0;
114 }
View Code

猜你喜欢

转载自www.cnblogs.com/Mandy-H-Y/p/11402121.html
今日推荐