标签:超时 mp3 理解 turn can else math 出现 pac
挺不错的概率DP,看似基础,实则很考验扎实的功底
这题很明显是个DP,为什么???找规律或者算组合数这种概率,N不可能给的这么友善。。。
因为DP一般都要在支持N^2操作嘛。
稍微理解一下,这DP[i][j]还是不好想啊,首先是写DP[I][j]的含义
首先我们想这道题是要求一个最优决策下的期望,那么这个我们的最优决策是什么???
决策就是:我们假设我这一次需要翻转K个硬币,我们不愿翻那些已经在正面的,而去翻那些没有在正面的
而如果剩余的反面的不足,我再去翻转正面的
那么给dp[i][j]一个含义,代表我现在进行第i轮,已经翻转了j个正面了,并用一个K表示我当前这一轮有K个正面朝上,再写出转移方程
dp[i+1][j+k]=dp[i][j]*C(z,i)*pow(0.5,z);
C(z,k)*pow(0.5,z);就代表,这一次需要在Z个硬币中,翻转上来K个的概率
而如果出现剩余面不足,我翻转反面,相减就可以
注意POW会超时,写一个p[i]的数组,表示(1/2)^i就可以了
#include<iostream> #include<string.h> #include<stdio.h> #include<algorithm> #include<math.h> using namespace std; double c[204][204]; double dp[204][204]; double p[204]; int main() { int n,m,k; int t,z; scanf("%d",&t); int tmp1,tmp2,tmp3; c[0][0]=1; for (int i=1;i<=100; i++) { c[i][0]=1; for (int j=1;j<=i;j++) { c[i][j]=c[i-1][j-1]+c[i-1][j]; } } p[0]=1; for (int i=1;i<=100;i++){ p[i]=p[i-1]*0.5; } while(t--) { scanf("%d%d%d",&n,&m,&z); memset(dp,0,sizeof(dp)); dp[0][0]=1; for (int i=0; i<m; i++)//本轮 { for (int j=0; j<=n; j++)//已经有j面向下了 { if(dp[i][j]==0)continue; for (int k=0; k<=z; k++)//如果在这t枚中得到了k个向下的 { if (j+z<=n)//全选面向下的 dp[i+1][j+k]+=dp[i][j]*p[z]*c[z][k]; else //选完剩余的还要选已经向上的 dp[i+1][k+n-z]+=dp[i][j]*p[z]*c[z][k]; } } } double ans=0; for (int i=1;i<=n;i++){ ans+=dp[m][i]*i; } printf("%.3lf\n",ans); } return 0; }
ACM-ICPC 2017 Asia Urumqi:A. Coins(DP)
标签:超时 mp3 理解 turn can else math 出现 pac
原文地址:https://www.cnblogs.com/bluefly-hrbust/p/9515303.html