题目链接:https://vjudge.net/problem/POJ-3071
题意:给你一个n,有2^n支球队在一个队列里,第i个球队战胜第j个球队的概率为a[i][j]。第一轮比赛,第1队和第2队打,赢了的进入下一轮的1队;第3队和第4队打,赢了的进入下一轮的2队。当经过n轮后,只剩下一个队,求哪个队获胜的概率高。
思路:概率dp,首先找到临界值,在第1回合中,第i队能进入下一回合的概率为 if(i%2) dp[i]=a[i][i+1]; else dp[i]=a[i][i-1]。对于之后的回合,我能进入的概率就等于我进入上一回合的概率*我的对手进入上一回合的概率*我打赢他的概率。最后再看哪队的概率高即可。
用scanf输入,用cin会超时
#include<bits/stdc++.h> #include<stdio.h> #include<string.h> #include<iostream> #include<algorithm> using namespace std; typedef long long ll; double dp[2005][2005],a[2005][2005]; int main() { int t; while(~scanf("%d",&t)) { if(t==-1) break; int n=1<<t; for(int i=1; i<=n; i++) for(int j=1; j<=n; j++) scanf("%lf",&a[i][j]); for(int i=1; i<=n; i++) { if(i%2) dp[0][i]=a[i][i+1]; else dp[0][i]=a[i][i-1]; } for(int i=1; i<t; i++) { int x=1<<i; for(int j=1; j<=(n>>i); j++) { if(j%2) { for(int k=(j-1)*x+1; k<=j*x; k++) { double sum=0; for(int h=j*x+1; h<=(j+1)*x; h++) sum+=a[k][h]*dp[i-1][h]; dp[i][k]=dp[i-1][k]*sum; } } else { for(int k=(j-1)*x+1; k<=j*x; k++) { double sum=0; for(int h=(j-2)*x+1; h<=(j-1)*x; h++) sum+=a[k][h]*dp[i-1][h]; dp[i][k]=dp[i-1][k]*sum; } } } } int ans=0; double s=0; for(int i=1; i<=n; i++) { if(dp[t-1][i]>s) { s=dp[t-1][i]; ans=i; } } printf("%d ",ans); } }