Alice和Bob两个人正在玩一个游戏,游戏有很多种任务,难度为p的任务(p是正整数),有1/(2^p)的概率完成并得到2^(p-1)分,如果完成不了,得0分。一开始每人都是0分,从Alice开始轮流做任务,她可以选择任意一个任务来做;而Bob只会做难度为1的任务。只要其中有一个人达到n分,即算作那个人胜利。求Alice采取最优策略的情况下获胜的概率。
输入格式:
一个正整数n,含义如题目所述。输出格式:
一个数,表示Alice获胜的概率,保留6位小数。样例输入:
1
样例输出:
0.666667
数据范围:
对于30%的数据,n≤10对于100%的数据,n≤500
时间限制:
1sec空间限制:
128MB概率DP
可以发现,对于每个游戏的状态,都是可以有前几个装态转移过来的
所以记dp[i][j]表示Ailce取得了i分,Bob取得了j分的最优概率
那么dp[n][j]($0leq j< n$)=1,其他状态都为0
因为进行游戏时有可能失败,那么dp[i][j]可能转移到自己
那么对于转移方程,可以将dp[i][j]移项移到一边,进行转移
设当前选择p个游戏
$dp[i][j]=dp[i][j]*(1-frac{1}{2^{p}})*frac{1}{2}+dp[i+2^{p-1}][j]*frac{1}{2^{p}}*frac{1}{2}+dp[i][j+1]*(1-frac{1}{2^{p}})*frac{1}{2}+dp[i+2^{p-1}][j+1]*frac{1}{2^{p}}*frac{1}{2}$
$(frac{1}{2}+frac{1}{2^{p+1}})dp[i][j]=dp[i+2^{p-1}][j]*frac{1}{2^{p}}*frac{1}{2}+dp[i][j+1]*(1-frac{1}{2^{p}})*frac{1}{2}+dp[i+2^{p-1}][j+1]*frac{1}{2^{p}}*frac{1}{2}$
$dp[i][j]=frac{dp[i+2^{p-1}][j]*frac{1}{2^{p}}*frac{1}{2}+dp[i][j+1]*(1-frac{1}{2^{p}})*frac{1}{2}+dp[i+2^{p-1}][j+1]*frac{1}{2^{p}}*frac{1}{2}}{frac{1}{2}+frac{1}{2^{p+1}}}$
然后对于每一个p,dp[i][j]取最大值即可
注意,此处是由较大的i,j推到较小的i,j,需要注意边界条件
#include <bits/stdc++.h> using namespace std; int n,z[20]; double dp[2010][2010]; int main() { scanf("%d",&n); for (int i=0;i<=n;i++) dp[n][i]=1; z[0]=1; for (int i=1;i<=15;i++) z[i]=z[i-1]*2; for (int i=n-1;i>=0;i--) { for (int j=n-1;j>=0;j--) { for (int p=1;p<=10;p++) { double now,r,sum=0;; now=1/((double)z[p]); r=1-0.5*(1-now);//r为转移方程的分母 sum=dp[min(i+z[p-1],n)][j]*now*0.5+dp[i][j+1]*(1-now)*0.5+dp[min(i+z[p-1],n)][j+1]*now*0.5; dp[i][j]=max(dp[i][j],sum/r); } } } printf("%.6lf ",dp[0][0]); }