LightOJ 1395 A Dangerous Maze (II) (概率dp)

题意:给出n扇门,每扇门都给出一个数x,若为正数,则表示在x时间后走出迷宫,若为负数,则表示在x时间后回到起点,你会记得最后k扇你走过的门(不会再走),求最后的期望时间。

题解:概率dp
这题的进阶版,原版不会记住走了哪扇门。一样的思路。
d p [ i ] dp[i] dp[i]表示记住 i i i扇门之后走出去还需要的期望时间。
n1:正数数量 n2:负数数量
s1:正数之和 s2:负数之和
①当k>=n2时,dp[k] = s1 / n1,相当于走任意一扇均可。
②当k<n2时,dp[k] = s1 / (n - k) + (n2 - k) * (dp[k] + s2 / n2) / (n - k),即走出去的期望时间+走回来再走出去的期望时间。化简得 d p [ k ] dp[k] dp[k]即可。因为不确定走的哪扇负数的门,既然求期望,直接对于单扇门取平均值即可。

确定了终值,往前递推。
方程为:dp[i] = s1 / (n - i) + (n2 - i) * (dp[i + 1] + s2 / n2) / (n - i)

#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<algorithm>
#include<queue>
#include<stack>
#include<cmath>
#include<vector>
#include<fstream>
#include<set>
#include<map>
#include<sstream>
#include<iomanip>
#define ll long long
using namespace std;
int t, n, k, a[111];
double dp[111];
int main() {
	int cas = 0;
	scanf("%d", &t);
	while (t--) {
		scanf("%d%d", &n, &k);
		double s1 = 0, s2 = 0, n1 = 0, n2 = 0;
		for (int i = 1; i <= n; i++) {
			scanf("%d", &a[i]);
			if (a[i] > 0) n1++, s1 += a[i];
			else n2++, s2 += -a[i];
		}
		if (n2 == n) {
			printf("Case %d: -1\n", ++cas);
			continue;
		}
		if (k >= n2) dp[k = n2] = s1 / n1;
		else dp[k] = (s1 / (n - k) + (n2 - k) * (s2 / n2) / (n - k)) / (1 - (n2 - k) / (n - k));
		for (int i = k - 1; i >= 0; i--) {
			dp[i] = s1 / (n - i) + (n2 - i) * (dp[i + 1] + s2 / n2) * 1.0 / (n - i);
		}
		printf("Case %d: %f\n", ++cas, dp[0]);
	}
	return 0;
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值