UVA10529 Dumb Bones

https://www.luogu.com.cn/problem/UVA10529

概率\(DP\)

若一件事发生的概率为\(p\),那么该事件发生的概率为\(\frac{1}{p}\)

达到骨牌不倒的期望次数为:

\[\frac{1}{1-pl-pr} \]

所以骨牌倒的期望次数为:

\[\frac{1}{1-pl-pr}-1=\frac{pl+pr}{1-pl-pr} \]

其中,向左倒的期望次数为:

\[\frac{pl+pr}{1-pl-pr}\times \frac{pl}{pl+pr}=\frac{pl}{1-pl-pr} \]

向左倒了,左边必须重建,一开始建了一次,倒了\(\frac{pl}{1-pl-pr}\)次,需要建:

\[\frac{pl}{1-pl-pr}+1=\frac{1-pr}{1-pl-pr} \]

\(So:\)

\[dp_i=\min_{1 \le j \le i} \frac{1-pr}{1-pl-pr} \times dp_{j-1}+\frac{1-pl}{1-pl-pr} \times dp_{i-j} +\frac{1}{1-pl-pr} \]

\(Code:\)

#include<cstdio>
#include<iostream>
#include<algorithm>
#define D double
#define N 1005
using namespace std;
int n;
D k1,k2,k3,pl,pr,dp[N];
int main()
{
    for (;'G'!='K';)
    {
        scanf("%d",&n);
        if (!n)
            break;
        scanf("%lf%lf",&pl,&pr);
        D k1=(1.0-pr)/(1-pl-pr);
        D k2=(1.0-pl)/(1-pl-pr);
        D k3=1.0/(1-pl-pr);
        for (int i=0;i<=n;i++)
            dp[i]=12345678987.0;
        dp[0]=0.0;
        for (int i=1;i<=n;i++)
            for (int j=1;j<=i;j++)
                dp[i]=min(dp[i],k1*dp[j-1]+k2*dp[i-j]+k3);
        printf("%.2lf\n",dp[n]);
    }
    return 0;
}

还可以利用决策单调性优化到\(O(n)\)

\(C++ Code:\)

#include<cstdio>
#include<iostream>
#include<algorithm>
#define D double
#define N 1005
using namespace std;
int n;
D k1,k2,k3,pl,pr,dp[N];
int main()
{
    for (;'G'!='K';)
    {
        scanf("%d",&n);
        if (!n)
            break;
        scanf("%lf%lf",&pl,&pr);
        D k1=(1.0-pr)/(1-pl-pr);
        D k2=(1.0-pl)/(1-pl-pr);
        D k3=1.0/(1-pl-pr);
        for (int i=0;i<=n;i++)
            dp[i]=12345678987.0;
        dp[0]=0.0;
        int k=0;
        for (int i=1;i<=n;i++)
        {
            dp[i]=k1*dp[k-1]+k2*dp[i-k]+k3;
            while (k+1<=i && k1*dp[k]+k2*dp[i-k-1]+k3<dp[i])
            {
                dp[i]=k1*dp[k]+k2*dp[i-k-1]+k3;
                k++;
            }
        }
        printf("%.2lf\n",dp[n]);
    }
    return 0;
}
posted @ 2020-08-06 15:08  GK0328  阅读(68)  评论(0编辑  收藏  举报