poj 1322 dp(马尔可夫链)

本文通过动态规划解决了一个关于从无限巧克力中取样并计算特定条件下剩余巧克力数量概率的问题。利用Markov链特性进行优化,避免了大规模计算,并提供了一个有效的实现方案。

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

题意:一个包里有无穷多个巧克力,每次从包里拿出一个巧克力放在桌子上。若桌子上出现两个相同的巧克力则立即吃掉。已知巧克力有c种颜色,问拿n次巧克力后,桌上有m颗巧克力的概率,输出结果精确到小数点后三位。

思路:整体思路是dp。dp[i][j]表示拿了i次之后桌子上剩下j个巧克力的概率。这道题的关键在于:N, M <= 1000000,而要求保留三位小数,所以n较大的情况可以省略计算。discuss里有人给出了证明(唉,概率学的不好,看也是懵懵懂懂):

这就是个典型的markov链:q(t+1)=P*q(t) -> q(n)=(P^n)*q(0)=Q'*D^n*Q*q(0)
P包含1、-1以及其他绝对值小于1的特征值,所以D的偶次方和奇次方会分别收敛到不同对角阵
所以n要区分奇偶。n的上界可以这么估计:
c=100的时候,可以得到绝对值小于1且最大的特征值0.98,那么由0.98^n<0.001可得n>342

#include <stdio.h>
#include <string.h>
#define N 1005
double dp[N][N];
int num,n,m;
int main(){
	freopen("a.txt","r",stdin);
	while(scanf("%d",&num) && num){
		int i,j;
		scanf("%d %d",&n,&m);
		memset(dp,0,sizeof(dp));
		if(m>num || m>n || ((m+n)%2==1)){
			printf("0.000\n");
			continue;
		}
		if(n>1001)//按照discuss那位仁兄的意思,应该大于342的就不用算了
			n = (n%2)?1001:1000;
		dp[0][0] = dp[1][1] = 1;//dp[0][0]不可少,因为输入可能(n,m)=(0,0)
		for(i = 2;i<=n;i++){
			for(j = 0;j<=num;j++){
				if(j!=0)
					dp[i][j] += dp[i-1][j-1]*(num-j+1)/num;
				if(j!=num)
					dp[i][j] += dp[i-1][j+1]*(j+1)/num;
			}
		}
		printf("%.3lf\n",dp[n][m]);
	}
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值