ACM-ICPC 2017 Asia Urumqi:A. Coins(DP)
Posted bluefly-hrbust
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ACM-ICPC 2017 Asia Urumqi:A. Coins(DP)相关的知识,希望对你有一定的参考价值。
挺不错的概率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 ",ans); } return 0; }
以上是关于ACM-ICPC 2017 Asia Urumqi:A. Coins(DP)的主要内容,如果未能解决你的问题,请参考以下文章
ACM-ICPC 2017 Asia Urumqi G. The Mountain
ACM-ICPC 2017 Asia Urumqi:A. Coins(DP) 组合数学
ACM-ICPC 2017 Asia Urumqi A. Coins期望dp
ACM-ICPC 2017 Asia Urumqi:A. Coins(DP)