zoj3329(期望DP)

本文探讨了一个涉及投掷三个不同最大值骰子的游戏,目标是计算当达到特定分数时,期望的投掷次数。通过设定初始条件和递推公式,作者解决了这一概率问题,最终给出了实现算法的C++代码。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题意:

有三个骰子,每个骰子最大分别是k1,k2,k3;

现在投骰子,如果刚好第一个,第二个,第三个投出了a,b,c,就把总分数归0,否则三个点数计入总分数,直到分数大于n;

问期望的投骰子的次数;


思路:

E[I] 代表已经有了i分,还需要投的次数的期望;

那么可以得到E[i] = E[0] * P + Σ(E[i + k] * pk[k]) + 1;

那么我们可以设为E[I] = p1[I] * E[0] + p2[i];

则可以得到E[i] = Σ(p1[i + k] )+ p + Σ(p2[i + k]) + 1;

得到p1[i] = Σ(p1[i + k]) + p  ; p2[i] = Σ(p2[i] + k) + 1;

就可以根据p1[0] ,p2[0] 算出E[0];


#include<cstdio>
#include<cstring>

const int N = 6 * 6 * 6;
double pk[N];
double p1[505];
double p2[505];
int n,k1,k2,k3,a,b,c;
int main() {
	int t;
	scanf("%d",&t);
	while(t--){
		memset(pk, 0, sizeof(pk));
		memset(p1, 0, sizeof(p1));
		memset(p2, 0, sizeof(p2));
		scanf("%d%d%d%d%d%d%d",&n,&k1,&k2,&k3,&a,&b,&c);
		double p = 1.0 / (k1 * k2 * k3);
		for(int i = 1; i <= k1; i++) {	
			for(int j = 1; j <= k2; j++) {
				for(int k = 1; k <= k3; k++) {
					if(i == a && j == b && k == c)
						continue;
					pk[i+j+k] += p;
				}	
			}
		}
		for(int i = n; i >= 0; i--){
			for(int j = 3; j <= k1+k2+k3 && i+j <= n; j++){
				p1[i] += p1[i + j] * pk[j];
				p2[i] += p2[i + j] * pk[j];
			}
			p1[i] += p;
			p2[i] += 1;
		}	
		printf("%.15lf\n",p2[0]/(1 - p1[0]));
	}
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值