UVA10529 Dumb Bones (完成度:40%)

题目链接:https://vjudge.net/problem/UVA-10529

知识点:  概率与期望,DP。

题目大意:

  现要放置 \(n\) 个多米诺骨牌,且每放置一块多米诺骨牌有 \(P_l\) 的概率向左倒,其左边相邻的骨牌也会随之倒下;有 \(P_r\) 的概率向右倒,其右边相邻的骨牌同上。问要放置 \(n\) 块相连的一排骨牌所需要的放置次数的最小期望是多少?

  \(1 \le n \le 100\)

  \(0 < P_l + P_r \le 0.5\)

解题思路:

  我们用动态规划的方法来解决这个问题。

  设 \(dp(i)\) 为放置 \(i\) 块相连的一排骨牌所需要的放置次数的最小期望,我们先给出状态转移方程:

  \(dp(i) = min\{ dp(i), \frac{dp(l) \cdot P_l + dp(r) \cdot P_r + 1}{1-P_l-P_r} + dp(l) + dp(r) \mid 0 \le l \le i, r = i-1-l \}\)  

  上式中,我用 \(l\) 表示放置第 \(i\) 块骨牌(即最后一块)的时候左边的相连的骨牌数,\(r\) 则表示右边的。我们可以用 \((l,r)\) 来表示我们放置最后一块骨牌的位置,则当我们在 \((l,r)\) 放置最后一块骨牌时,放置这 \(i\) 块连续的骨牌所需要的次数的期望为 \(E = E(i) + dp(l) +dp(r)\),我们事先已经知道了 \(dp(k) \{0 \le k < i\}\),故重点就在于求解 \(E(i)\) ,即放置第 i 块所需的放置次数的期望。首先,我们需要知道:每放置一块多米诺骨牌有 \(1 - P_l - P_r\) 的概率不会倒。接下来,我们分成如下三种情况来讨论:

  1、放置一次即成功,有 \(1 - P_l - P_r\) 的概率。则放置次数的期望为:\(\frac{1}{1 - P_l - P_r}\) ;

  2、放置以后向左倒,有 \(P_l\) 的概率。我们需要先将左边的骨牌放置好,我们需要放置成功 \(dp(l)\) 次,每一次的成功概率都为 \(1 - P_l - P_r\),则需要的次数的期望为 \(\frac{dp(l)}{1-P_l-P_r}\),当然,我们也不能忘了乘上 \(P_l\),则最终的期望值为:\(\frac{P_l \cdot dp(l)}{1-P_l-P_r}\);

  3、放置以后向右倒同理。

  于是,我们不难推出:

  \(E = \frac{dp(l) \cdot P_l + dp(r) \cdot P_r +1}{1 - P_l - P_r} + dp(l) + dp(r)\)  .

  一切也就顺理成章了。

AC代码:

 1 #include <iostream>
 2 #include <cstdio>
 3 
 4 using namespace std;
 5 const int maxn=1010;
 6 const double inf=0x7fffffff;
 7 double dp[maxn];
 8 int main()
 9 {
10     int n;
11     double pl,pr;
12     while(scanf("%d",&n)==1&&n){
13         scanf("%lf%lf",&pl,&pr);
14         for(int i=1;i<=n;i++)   dp[i]=inf;
15         dp[0]=0;
16         int l,r;
17         for(int i=1;i<=n;i++){
18             for(l=0;l<i;l++){
19                 r=i-1-l;
20                 dp[i]=min(dp[i],(dp[l]*pl+dp[r]*pr+1)/(1-pl-pr)+dp[l]+dp[r]);
21             }
22         }
23         printf("%.2lf\n",dp[n]);
24     }
25     return 0;
26 }

 

  PS: 此题还有一种 \(O(nlog n)\) 和一种 \(O(n)\) 的算法,未完待续。

posted @ 2017-11-20 19:37  Blogggggg  阅读(294)  评论(0编辑  收藏  举报