poj 2096 Collecting Bugs

本文详细解析了POJ2096问题——收集Bug问题,并使用概率动态规划的方法来解决该问题。文章介绍了如何通过逆向推导的方式得出期望值,给出了一种清晰的解题思路及代码实现。

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

题目:poj 2096 Collecting Bugs

tag:概率dp

思路:关于期望的问题

除了上次多校之外好像没接触过期望类的问题,最近看了刘汝佳的厚白书上几个题,对马尔可夫过程完全不理解,同时也不明白所谓的”期望的线性和全期望公式“是啥。。。

不过看了上次某篇博客里说”一般情况概率是正着推,期望是倒着推”(尼玛,老子怎么揣测就不对,我怎么知道for循环式正着过去,还是逆着过来)

算了  不扯淡了  慢慢看吧  总会理解别人说的那几句话的

同白书143面那个马尔可夫过程那题一样,那个题是得到这样一个等式  f(x)=1+f(x)*(1-g(x)/p(x))+sum(f(x/y))*1/p(x) (x能整除y)   (f(x)表示最后得到1的期望)

同理,那么这题的等式为:

             设dp[i][j]为已经发现i个bug,类属于j个bug的时候消除其余的bug所要的天数期望 

             dp[i][j] = 1 + dp[i+1][j] *(n-i)/n*j/s + dp[i+1][j+1]*(n-i)*(s-j) /s + dp[i][j+1]*i/n*(s-j)/s + dp[i][j]*i/n*j/s

     化简之后得到:

             dp[i][j] = ( dp[i+1][j] *(n-i)/n*j/s + dp[i+1][j+1]*(n-i)*(s-j) /s + dp[i][j+1]*i/n*(s-j)/s )/ (1 - i/n * j/s) 

至于为什么这个题的for循环是逆着的,这个吃夜宵的时候想通了,开始的时候呢(假设dp[i][j] 表示消除全部bug的概率,求个倒数不就是期望了?我想的是从每一个状态到另外四个相邻状态的关系可以有个递推,可是for循环怎么写呢,尤其是那种从自己到自己的情况该怎么写呢。= = 我是不是太天真了。)看了下别人的代码,联想到白书上那道求期望的,= = 尼玛,不跟书上是一个意思么,至于为什么逆着,是因为开始的时候已经解决n种bug和s种子系统的情况需要解决其余的bug的期望(已经没有需要解决的bug了)是0,然后一直推到bug数和子系统数为0的情况。

呵呵。。。别人眼里的大水题,我竟然搞了这么久,这算是入门题么 = =


#include <cstdio>
#include <iostream>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;
double dp[1010][1010];
int main()
{
	int s,n;
	while(scanf("%d%d",&n,&s)!=EOF)
	{
		dp[n][s]=0;
		for(int i=n;i>=0;i--)
			for(int j=s;j>=0;j--)
			{
				if(i==n&&j==s)
					continue;
				dp[i][j]=(1+
					dp[i+1][j]*(n-i+0.0)/n*j/s+
					dp[i+1][j+1]*(n-i+0.0)/n*(s-j+0.0)/s+
					dp[i][j+1]*(i+0.0)/n*(s-j)/s)/(1-(i*j+0.0)/(n*s+0.0));
			}
		printf("%.4lf\n",dp[0][0]);
	}
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值