poj 3071 Football

        题意:有2^n支球队,按编号顺序比赛,胜者晋级,与上轮的胜者继续按编号顺序比赛...已知每两支球队间输赢的概率,问那支球队最终最有可能夺冠。

        思路:概率dp,一轮一轮算,算到最后一轮找出来最大值。


#include <iostream>       
#include <stdio.h>       
#include <cmath>       
#include <algorithm>       
#include <iomanip>       
#include <cstdlib>       
#include <string>       
#include <memory.h>       
#include <vector>       
#include <queue>       
#include <stack>       
#include <map>     
#include <set>     
#include <ctype.h>       
#define INF 1000000     
#define ll long long   
#define min3(a,b,c) min(a,min(b,c))   
    
using namespace std;    

int n,num;

double p[130][130];
double ans[10][130];

void findlr(int x,int k,int& l,int& r){
    l=1;
    r=num;
    int time=n-k+1;
    while(time--){
        int mid=(l+r)/2;
        if(time==0){
            if(x<=mid){
                l=mid+1;
            }else{
                r=mid;
            }
        }else{
            if(x<=mid){
                r=mid;
            }else{
                l=mid+1;
            }
        }
    }
} 

int main(){
    while(cin>>n){
        if(n==-1)break;
        num=1<<n;
        
        for(int i=1;i<=num;i++){
            for(int j=1;j<=num;j++){
                cin>>p[i][j];
            }
        }
        
        //init
        for(int i=1;i<=num;i++){
            ans[0][i]=1.0;
        }
        
        //dp
        int l,r;
        int winner;
        double _max=-1.0;
        for(int i=1;i<=n;i++){
            for(int j=1;j<=num;j++){
                findlr(j,i,l,r);
                ans[i][j]=0.0;
                for(int k=l;k<=r;k++){
                    ans[i][j]+=ans[i-1][j]*ans[i-1][k]*p[j][k];
                }
                if(i==n&&ans[i][j]>_max){
                    _max=ans[i][j];
                    winner=j;
                }
            }
        }
        cout<<winner<<endl;
    }
    return 0;
}



你可能感兴趣的:(poj,概率DP)