POJ - 3071 Football
阿新 • • 發佈:2020-09-23
題目連結: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\n",ans); } }