【UVA 10529】多米诺骨牌(Dumb Bones)(BSOI4920)

来源:互联网 发布:淘宝香港代购靠谱吗 编辑:程序博客网 时间:2024/06/05 07:03

UVA 10529】多米诺骨牌(Dumb Bones)

Description

        你试图把一些多米诺骨牌排成直线,然后推倒它们。但是如果你在放骨牌的时候不小心把刚放的骨牌碰倒了,它就会把相临的一串骨牌全都碰倒,而你的工作也被部分的破坏了。比如你已经把骨牌摆成了DD__DxDDD_D的形状,而想要在x这个位置再放一块骨牌。它可能会把左边的一块骨牌或右边的三块骨牌碰倒,而你将不得不重新摆放这些骨牌。这种失误是无法避免的,但是你可以应用一种特殊的放骨牌方法来使骨牌更多的向一个方向 。
        给定n,表示要放n个骨牌,每次放下骨牌,有可能向左倒的概率为pl,向右倒的概率为pr,如果倒下,会将那一侧的骨牌全部推倒,可以选择位置先后放骨牌,问说一种放骨牌次数最少的期望是多少?

Input

输入一个整数n,2个实数pl,pr。

Output

输出一个实数,放n张骨牌次数最少的期望,结果保留两位小数。

Sample Input

2
0.1  0.1

Sample Output

2.66

Hint

对于100%的数据,2<=n<=10^5,pl+pr<1.0。

Solution

        我们需要注意的是,每一次摆放的左右倾倒概率是一样的,所以说在一个给定长度的序列中,有且仅有一个点,使得在这个点放置最后一块骨牌时,所需的期望次数最小。这一点略微有点像黄金分割,分割出的两条线段各有一个黄金分割点。至于这个多米诺骨牌的分割点,其实是决定与pl和pr的。

        我们很幸运地发现,每一个点的pl和pr是一样的,那么我们的分割点比例总是一样的,就可以用线性的方法递推或者是递归了。对于每一段长度为n的骨牌,我们将其期望设为V[n],放好某一点的期望为E[x],最优的最后放置点为i,那么就有如下表达式:

        v[n]=v[i-1]+E[i]+v[n-i]

              =v[i-1]+(1.0-pl-pr)+pl*(1.0+v[i-1]+E[i])+pr*(1.0+v[n-i]+E[i])+v[n-i]

              =v[i-1]+(pl*v[i-1]+pr*v[n-i]+1)/(1.0-pl-pr)+v[n-i]

至此,题目在O(N)的时间内得解。

CODE

#include<iostream>#include<cstdio>using namespace std;double f[100005];double pl,pr,ans;int n;inline double cal(int n,int i){return (pl*f[i-1]+pr*f[n-i]+1)/(1.0-pl-pr)+f[i-1]+f[n-i];//计算期望 }int main(){cin>>n;int i,j,x=1;cin>>pl>>pr;f[0]=0;f[1]=1.0/(1.0-pl-pr);//初始化,0张牌期望为0,一张牌期望为既不左倒也不右倒的概率 for(i=2;i<=n;i++){f[i]=cal(i,x);while(x<i&&cal(i,x+1)<f[i]){f[i]=cal(i,x+1);x++;}//更优的决策点一定在上一次决策点之后 }printf("%.2lf",f[n]);//保留两位 return 0;} 

+
0 0
原创粉丝点击