概率dp poj 3071
题目首先给出一个n,表示比赛一共进行n轮,那么队伍就有2^n只队伍
输入一个2^n*2^n的矩阵,p[i][j]代表队伍i打败队伍j的概率
dp[i][j]代表第i轮比赛的时候,队伍j赢的概率
首先初始化时,dp[0][i]=1,在没有比赛时每个队伍都是赢的
dp[i][j]+=dp[i-1]j[*dp[i-1][k]*p[j][k]:要求j和k的上一轮都是赢家的概率再乘以本轮j打败k的概率
特别注意,队伍只能相邻的打,相邻的队伍转换成二进制时,高位相同,到第i位正好相反
可以用 if(((j>>(i-1))^1)==(k>>(i-1)))来判断,是否相邻,或者是下面代码中我所用的方法
因为最开始一轮两两相邻的打,只有二进制中的最后一位不一样,第二轮时,上一轮的赢家相邻的打,是第二位不一样
很巧妙
————————————————
版权声明:本文为CSDN博主「Cherry_0525」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_41037114/article/details/81906416
1 #include<cstdio> 2 #include<algorithm> 3 #include<string.h> 4 #include<math.h> 5 using namespace std; 6 const int maxn=1<<8; 7 double p[maxn][maxn]; 8 double dp[maxn][maxn]; 9 int main() 10 { 11 int n; 12 while(scanf("%d",&n)!=EOF){ 13 if(n==-1) break; 14 int len=1<<n; 15 for(int i=1;i<=len;i++) 16 for(int j=1;j<=len;j++){ 17 scanf("%lf",&p[i][j]); 18 } 19 memset(dp,0,sizeof(dp)); 20 for(int i=1;i<=len;i++) dp[0][i]=1.0; 21 for(int i=1;i<=n;i++){ 22 for(int j=1;j<=len;j++) 23 for(int k=1;k<=len;k++){ 24 if((((j-1)>>(i-1))^1)==((k-1)>>(i-1))) //这是一个判断相邻的操作。 25 dp[i][j]+=dp[i-1][j]*dp[i-1][k]*p[j][k]; 26 27 } 28 } 29 double mx=0.0; 30 int ansbase=0; 31 for(int i=1;i<=len;i++) 32 if(dp[n][i]>mx){ 33 mx=dp[n][i]; 34 ansbase=i; 35 } 36 printf("%d\n",ansbase); 37 } 38 return 0; 39 }