UVa10529 Dumb Bones ( 期望概率DP )

51 篇文章 1 订阅
13 篇文章 0 订阅

UVa10529 Dumb Bones

原题地址https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=1470

题意:
你试图把一些多米诺骨牌排成直线,然后推倒它们。但是如果你在放骨牌的时候不小心把刚放的骨牌碰倒了,它就会把相临的一串骨牌全都碰倒,而你的工作也被部分的破坏了。 比如你已经把骨牌摆成了DD__DxDDD_D的形状,而想要在x这个位置再放一块骨牌。它可能会把左边的一块骨牌或右边的三块骨牌碰倒,而你将不得不重新摆放这些骨牌。 这种失误是无法避免的,但是你可以应用一种特殊的放骨牌方法来使骨牌更多的向一个方向倒下。 给出你要摆放的骨牌数目,以及放骨牌时它向左和向右倒的概率,计算你为完成任务摆放的骨牌数目的平均数。假设你使用了最佳的摆放策略。
输入将包含至多100个测试点,每个测试点占一行,包含需要摆放的骨牌数目n (1≤n≤1000),以及两个非负实数Pl, Pr,表示骨牌向左和向右倒的概率。保证1<Pl+Pr≤0.5。 最后一个测试点包含一个数0。对于每个测试点输出题目要求的数目,保留两位小数。

数据范围
数据组数<=100, 1≤n≤1000 ,1<Pl+Pr≤0.5

题解:
E=El+Er+F(期望再放几次)
=El+Er+(1-pl-pr) * 不倒期望再放几次+pl * 向左倒期望再放几次+pr *向右倒期望再放几次
F= (1-pl-pr) * 不倒期望再放几次+pl * 向左倒期望再放几次+pr *向右倒期望再放几次
我们考虑怎么求 F
向左倒了,我们就要把左边的摆好,然后又回到了已有El ,Er,求E的状况。
此时期望再放几次就是 F
向右边倒同理
F=(1-pl-pr)* 1+pl* (El+F)+pr*(Er+F)
当然我们可以移项 求出F
但是考虑到 F=E-El-Er 我们得到了更简洁的表达形式
即:
F=(1-pl-pr)* 1+pl* (El+E-El-Er)+pr*(Er+F+E-El-Er)
=(1-pl-pr)* 1+pl* (E-Er)+pr*(E-El)
E=El+Er+F
=El+Er+(1-pl-pr)* 1+pl* (E-Er)+pr*(E-El)
把E移项提出来得:
E=((1-pl)* Er + (1-Pr)* El + 1)/(1-pl-pr)
因为每步都采取最优策略
对于每个Ei,我们要枚举所有的k(1<=k<=i),作为放的位置
El=E(k-1) Er=E(i-k)
E=min(((1-pl)*Er + (1-pr)*El + 1)/(1-pl-pr))

至此,得到n^2做法

代码:

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
const int N=1005;
const double inf=0x3f3f3f3f;
int T,n;
double pl,pr,E[N];
double min(double A,double B)
{
    return A<B?A:B;
}
int main()
{
    scanf("%d",&n);
    while(1)
    {   
        if(n==0) break;
        scanf("%lf%lf",&pl,&pr);
        E[0]=0;
        for(int i=1;i<=n;i++)
        {
            E[i]=inf;
            for(int k=1;k<=i;k++)
            {
                int l=k-1; int r=i-k;
                double cur=((1-pl)*E[r]+(1-pr)*E[l]+1.0)/(1-pl-pr);
                E[i]=min(E[i],cur);
            }   
        }
        printf("%0.2lf\n",E[n]);
        scanf("%d",&n);
    }
    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值