1. 程式人生 > 實用技巧 >POJ - 3071 Football

POJ - 3071 Football

題目連結: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); } }