POJ 3071 Football(概率问题)
转载请注明出处,谢谢http://blog.csdn.net/acm_cxlove/article/details/7854526 by---cxlove
题目:有2^n个队,相邻的两两打淘汰赛,,求最后哪个队夺冠的概率最大
http://poj.org/problem?id=3071
dp[i][j]表示第i轮的时候,第j去支队伍赢的概率。
那么dp[i][j]的前提就是i-1轮的时候,j是赢的,而且第i轮赢了对方
接下来就是找到第i轮的时候,他的可能队手
通过二进制可以发现规律,所有高位是一样的,第i位刚好相反,所以用位运算可以巧妙解决,见代码
dp[i][j]=sigma(dp[i-1][j]*dp[i-1][k]*p[j][k])
#include<iostream>#include<cstdio>#include<algorithm>#include<cstring>#include<cmath>#define eps 1e-10#define N (1<<7)+5#define inf 1<<20#define zero(a) (fabs(a)<eps)#define lson (step<<1)#define rson (step<<1|1)using namespace std;double p[N][N];double dp[10][N];int main(){ int n; while(scanf("%d",&n)!=EOF&&n!=-1){ for(int i=0;i<(1<<n);i++) for(int j=0;j<(1<<n);j++) scanf("%lf",&p[i][j]); memset(dp,0,sizeof(dp)); for(int i=0;i<(1<<n);i++) dp[0][i]=1; for(int i=1;i<=n;i++){ for(int j=0;j<(1<<n);j++){ for(int k=0;k<(1<<n);k++){ if(((j>>(i-1))^1)==(k>>(i-1))) dp[i][j]+=dp[i-1][k]*dp[i-1][j]*p[j][k]; } } } double ans=0; int idx=-1; for(int i=0;i<(1<<n);i++) if(dp[n][i]>ans){ ans=dp[n][i]; idx=i+1; } printf("%d\n",idx); } return 0;}