您的位置:首页 > 其它

Collecting Bugs POJ - 2096 期望dp

2017-11-04 20:41 393 查看
题意:有s个子结构,n种bug,每天都会发现一个bug,问发现n种bug,且每个子结构中都有bug的期望是多少

分析:

开始想状态是:

dp[i][j]:bug在i个子结构中,j种bug的期望天数,

然后由dp[i-1][j],dp[i-1][j-1],dp[i][j-1],dp[i][j]转移过来,

但是这四种状态转移到dp[i][j]的概率是一样的么?

比如:
假设 dp[i]:表示转移到i的期望步数。从1开始,那么dp[1]=1;
1可以转移到2,3,
2可以转移到3,4
3可以转移到4,5
这个时候我们要求dp[4],4可以由2,3转移过来,那么$dp[4]=1/2(dp[2]+dp[3])+1$;
这个时候上面的说法是错的,因为2和3转移到4的概率并不是相同的,因为2还会转移到3.倒着推的好处在哪呢,4转移到5,6,的概率是一样的。


通过上面的例子我们也清楚了不能直接顺着推(如果还是不相信的话,可以将这四个概率加起来,会发现比1小)。也不符合dp的后效性。

这个时候我们可以反着来推

dp[i][j]:bug在i个子结构,j种bug,离目标还需要的期望天数

可以转移到以下四个状态

dp[i+1][j]: 概率p1=(1−i/s)
4000
∗(j/n)

dp[i][j+1]:概率p2=(i/s)∗(1−j/n)

dp[i+1][j+1]:概率p3=(1−i/s)∗(1−j/n)

dp[i][j]:概率p4=i/s∗j/n

dp[s]
=0;

dp[i][j]=(p1*dp[i+1][j]+p2*dp[i][j+1]+p3*dp[i+1][j+1]+1)/(1-p4);

using namespace std;
#define ll long long
#define mem(a,b) memset(a,b,sizeof(a))
const int maxn = 1e3+10;
double dp[maxn][maxn];
int main()
{
int s,n;
while(scanf("%d %d",&n,&s)!=EOF)
{
mem(dp,0);
for(int i=s;i>=0;i--)
{
for(int j=n;j>=0;j--)
{
if(i==s&&j==n) continue;
double p1=(double)(s-i)/s,p2=(double)(n-j)/n,p3=(double)i/s,p4=(double)j/n;
dp[i][j]=((p1*p4)*dp[i+1][j]+(p3*p2)*dp[i][j+1]+(p1*p2)*dp[i+1][j+1]+1)/(1-p3*p4);
}
}
printf("%.4f\n",dp[0][0]);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: