蒟蒻の算法题(~~完全不会~~的期望)01

tips:就是要用~~表示删除 太蒻了
现在有一张图, 有 v<=300v<=300 个节点

你需要从 c1c1 到 c2c2 到 cn(n<=2000)cn(n<=2000)

现在你有 mm 次机会把 cici 换为 didi, 对于第 ii 个, 成功的概率为 kiki

求走完整个路程的期望路径长度
本题为期望 dpdp , 从上一个状态转移过来(听dalao说还有一种是计算本状态对后面状态的贡献)

具体来说, 这个状态可以由以上 nn 个状态得到, 每个状态权值为 wiwi, 其中第 ii 个状态到此状态的概率为 kiki, 那么有此状态可以表示为
dp[now]=∑i=1nwi∗ki
本题状态为:

dp[i][j][0/1]dp[i][j][0/1] 代表选到第 ii 门课用掉 jj 次机会, 此次申请或不申请的期望值

所有转移详细记录在注释中

答案自然在 minmi=0min(dp[n][i][0],dp[n][i][1])

#include<bits/stdc++.h>
using namespace std;
#define LL long long
#define REP(i, x, y) for(int (i) = (x);(i) <= (y);(i)++)
using namespace std;
int RD(){
    int out = 0,flag = 1;char c = getchar();
    while(c < '0' || c >'9'){if(c == '-')flag = -1;c = getchar();}
    while(c >= '0' && c <= '9'){out = out * 10 + c - '0';c = getchar();}
    return flag * out;
    }
const int maxn = 4019, maxv = 319;
int num, numc, numv, nr;
int map[maxv][maxv];
int c[maxn], d[maxn];
double k[maxn];
double dp[maxn][maxn][2];
void floyd(){
	REP(i, 1, numv)map[i][i] = 0;
	REP(k, 1, numv)REP(i, 1, numv)REP(j, 1, numv){
		map[i][j] = min(map[i][j], map[i][k] + map[k][j]);
		}
	}
int dist(int x, int y){return map[x][y];}
void init(){
	REP(i, 1, numv)REP(j, 1, numv)map[i][j] = 1e9;
	REP(i, 1, num)REP(j, 0, numc)dp[i][j][0] = dp[i][j][1] = 1e9;
	}
int main(){
	num = RD(), numc = RD(), numv = RD(), nr = RD();
	init();
	REP(i, 1, num)c[i] = RD();
	REP(i, 1, num)d[i] = RD();
	REP(i, 1, num)cin>>k[i];
	REP(i, 1, nr){
		int u = RD(), v = RD(), dis = RD();
		map[u][v] = min(map[u][v], dis);
		map[v][u] = map[u][v];
		}
	floyd();
	dp[1][0][0] = dp[1][1][1] = 0;//选或不选都为起点
	REP(i, 2, num){
		int m = min(numc, i);
		REP(j, 0, m){//可以不申请换教室, 从0开始
			dp[i][j][0] = min(//本次不申请
			dp[i - 1][j][0] + dist(c[i], c[i - 1]),//上次不申请
			dp[i - 1][j][1]//上次申请
			+ dist(c[i], d[i - 1]) * k[i - 1]//申请成功
			+ dist(c[i], c[i - 1]) * (1 - k[i - 1])//申请失败
			);
			if(!j)continue;
			dp[i][j][1] = min(//本次申请
			dp[i - 1][j - 1][0]//上次不申请
			+ dist(d[i], c[i - 1]) * k[i]//本次成功
			+ dist(c[i], c[i - 1]) * (1 - k[i]), //本次失败
			dp[i - 1][j - 1][1]//上次申请
			+ dist(c[i], c[i - 1]) * (1 - k[i]) * (1 - k[i - 1])//0->0
			+ dist(d[i], c[i - 1]) * k[i] * (1 - k[i - 1])//0->1
			+ dist(c[i], d[i - 1]) * (1 - k[i]) * k[i - 1]//1->0
			+ dist(d[i], d[i - 1]) * k[i] * k[i - 1]//1->1
			);
			}
		}
	double ans = 100000019;
	REP(i, 0, numc){
		ans = min(ans, dp[num][i][0]);
		ans = min(ans, dp[num][i][1]);
		}
	printf("%.2lf\n", ans);
	return 0;
	}
  • 4
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值