• [洛谷P1850]换教室 概率与期望


    题目←

    要分清哪些状态是独立的,哪些状态对期望有影响
    一开始傻傻的在通过和没通过之间取min……
    事实上,在求期望的前提下,真正影响的决策是是否申请
    以及万万没想到Floyd打次了
    map[i][i] = 0才对


    发现当前时间段的状态仅仅可以由上一时间段的状态转移来
    上一时间段的情况可能有以下几种

    1、申请了换教室,过
    2、申请了换教室,没过
    3、没申请换教室

    如果没有概率且我们要求的只是最大/最小值,就在换、未换两种情况里取min
    但发现我们每个时间段需要做的决策不是换/不换
    而是申请/不申请
    (1、2两种状态不是我们能够决策的,他们出现的概率已经确定)
    所以每个时间点就申请/不申请划分状态
    dp[i][j][0/1]表示i时间段,总共申请了j段,而第i段申请/未申请

    来梳理状态间的关系:
    (B_i)为原教室,(C_i)为更换后的教室
    求i - 1 ~ i距离的时候,可能出现的状况有:
    1、第i - 1时间段在(B_{i - 1}),第i时间段在(B_i)
    2、第i - 1时间段在(C_{i - 1}),第i时间段在(B_i)
    3、第i - 1时间段在(B_{i - 1}),第i时间段在(C_{i})
    4、第i - 1时间段在(C_{i - 1}),第i时间段在(C_{i})

    当阶段i我们选择不申请时:
    第i时间段在(B_i)的概率:1
    第i时间段在(C_i)的概率:0

    若从第i - 1阶段未申请的状态转移过来
    第i - 1时间段在(B_{i - 1})的概率:1
    第i - 1时间段在(C_{i - 1})的概率:0
    综上,这个转移为

    [dp[i][j][0] = dp[i - 1][j][0] + map[$B_{i - 1}$][$B_{i}$] * 1 * 1 + map[$C_{i - 1}$][$B_{i}$] * 0 * 1 + map[$B_{i - 1}$][$C_{i}$] * 1 * 0 + map[$C_{i - 1}$][$C_{i}$] * 0 * 0;]

    类比一下,若从i - 1申请了的状态转移过来
    第i时间段在(B_i)的概率:1
    第i时间段在(C_i)的概率:0
    第i - 1时间段在(B_{i - 1})的概率:P[i - 1]
    第i - 1时间段在(C_{i - 1})的概率:1 - P[i - 1]

    这个转移为

    [dp[i][j][0] = dp[i - 1][j][1] + map[$B_{i - 1}$][$B_{i}$] * (1 - P[i]) * 1 + map[$C_{i - 1}$][$B_{i}$] * P[i] * 1 + map[$B_{i - 1}$][$C_{i}$] * 1 * 0 + map[$C_{i - 1}$][$C_{i}$] * 0 * 0]

    继续类比
    当阶段i我们选择申请时:
    转移同样有两种可能,i - 1申请/未申请
    i - 1未申请时:
    第i时间段在(B_i)的概率:P[i]
    第i时间段在(C_i)的概率:(1 - P[i])
    第i - 1时间段在(B_{i - 1})的概率:1
    第i - 1时间段在(C_{i - 1})的概率:0
    这个转移为:

    [dp[i][j][0] = dp[i - 1][j][0] + map[$B_{i - 1}$][$B_{i}$] * 1 * P[i] + map[$C_{i - 1}$][$B_{i}$] * 0 * P[i] + map[$B_{i - 1}$][$C_{i}$] * 1 * (1 - P[i]) + map[$C_{i - 1}$][$C_{i}$] * 0 * (1 - P[i])]

    若从i - 1申请转来
    第i时间段在(B_i)的概率:P[i]
    第i时间段在(C_i)的概率:(1 - P[i])
    第i - 1时间段在(B_{i - 1})的概率:P[i - 1]
    第i - 1时间段在(C_{i - 1})的概率:1 - P[i - 1]
    这个转移为:

    [dp[i][j][0] = dp[i - 1][j][0] + map[$B_{i - 1}$][$B_{i}$] * P[i - 1] * P[i] + map[$C_{i - 1}$][$B_{i}$] * (1 - P[i - 1]) * P[i] + map[$B_{i - 1}$][$C_{i}$] * P[i - 1] * (1 - P[i]) + map[$C_{i - 1}$][$C_{i}$] * (1 - P[i - 1]) * (1 - P[i])]

    代码如下:

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #define INF 1061109567
    #define LL long long
    using namespace std;
    const int M = 2000 + 50;
    LL map[M][M],c;
    double dp[M][M][2],P[M];
    int n,m,v,e;
    int a,b,B[M],C[M];
    int main(){
    	scanf("%d%d%d%d",&n,&m,&v,&e);
    	for(int i = 1;i <= n;i ++){
    		scanf("%d",&B[i]);
    	}
    	for(int i = 1;i <= n;i ++){
    		scanf("%d",&C[i]);
    	}
    	for(int i = 1;i <= n;i ++){
    		scanf("%lf",&P[i]);
    	}
    	memset(map,0x3f,sizeof(map));
    	for(int i = 1;i <= v;i ++){
    		map[i][i] = 0;
    	}
    	for(int i = 1;i <= e;i ++){
    		scanf("%d%d%lld",&a,&b,&c);
    		if(map[a][b] > c)map[a][b] = c,map[b][a] = c;
    	}
    	for(int k = 1;k <= v;k ++){
    		for(int i = 1;i <= v;i ++){
    			for(int j = 1;j <= v;j ++){
    				if(map[i][j] > map[i][k] + map[k][j] && map[i][j] != INF && map[k][j] != INF)
    					map[i][j] = map[i][k] + map[k][j];
    			}
    		}
    	}
    	for(int i = 0;i <= n;i ++){
    		for(int j = 0;j <= n;j ++)
    		dp[i][j][0] = dp[i][j][1] = INF;
    	}
    	dp[1][0][0] = dp[1][1][1] = 0;
    	for(int i = 2;i <= n;i ++){
    		for(int k = min(i,m);k >= 0;k --){
    			dp[i][k][0] = min(dp[i][k][0],dp[i - 1][k][0] + map[B[i - 1]][B[i]]);
    			dp[i][k][0] = min(dp[i][k][0],dp[i - 1][k][1] + map[B[i - 1]][B[i]]*(1 - P[i - 1])
    				+ map[C[i - 1]][B[i]]*P[i - 1]);
    			//if(i >= 3 && !dp[i][k][0])printf("haha%d
    ",i);
    			if(k >= 1){
    				dp[i][k][1] = min(dp[i][k][1],dp[i - 1][k - 1][0]
    											 + map[B[i - 1]][B[i]]*(1 - P[i]) + map[B[i - 1]][C[i]]*P[i]);
    				dp[i][k][1] = min(dp[i][k][1],dp[i - 1][k - 1][1] + map[B[i - 1]][B[i]]*(1 - P[i - 1])*(1 - P[i])
    				+ map[C[i - 1]][B[i]]*P[i - 1]*(1 - P[i]) + map[B[i - 1]][C[i]]*(1 - P[i - 1])*P[i]
    				+ map[C[i - 1]][C[i]]*P[i - 1]*P[i]);
    			}
    		}
    	}
    	double ans = INF;
    	for(int i = 0;i <= m;i ++){
    		ans = min(ans,min(dp[n][i][0],dp[n][i][1]));
    	}
    	/*
    	ans = 0;
    	for(int i = 2;i <= n;i ++){
    		ans += map[B[i - 1]][B[i]];
    	}*/
    	printf("%.2lf",ans);
    }
    
  • 相关阅读:
    微信小程序开发前期准备
    怎样在vs2013和vs2015中实现自动编译sass
    在MVC中使用Bundle打包压缩js和css
    Html5 突破微信限制实现大文件分割上传
    Automapper 实现自动映射
    Polly一种.NET弹性和瞬态故障处理库(重试策略、断路器、超时、隔板隔离、缓存、回退、策略包装)
    关于transactionscope 事务的脏数据
    IIS设置session时长
    已禁用对分布式事务管理器(MSDTC)的网络访问的解决方法之一
    DAL.SQLHelper 的类型初始值设定项引发异常的处理
  • 原文地址:https://www.cnblogs.com/loi-pingxing/p/7786544.html
Copyright © 2020-2023  润新知