poj_3071 Football (probability dp)

 Go directly to the state transition equation:

Let dp[i][j] be the probability that the jth team wins the i-th round.

Then in the initial state, dp[0][j]=1;//That is, the 0th round all won

d[i][j]=sum(d[i-1][j]*d[i-1][k]*win[j][k])//That is to find all possible teams with j in the first If the k team in the i-round duel, then the probability of the i team defeating the k team is: the probability of the i-1th team j team qualifying * the i-1th round the probability of the kth team appearing * the i-th round j team defeating the k team The probability. Traverse all the possible values ​​of k to find the probability sum, and the result is d[i][j].

Among them, how to find all possible k-teams is a difficult point.

The general idea is to group first:

For example, a total of 8 teams

In the first round, the grouping is (1, 2) (3, 4) (5, 6) (7, 8)

In the second round, the grouping is ((1|2), (3|4)) ((5|6), (7|8))

Therefore, we may first divide by group number:

In the first round, the first group has 1, 2; the second group has 3, 4; the third group has 5, 6; the fourth group has 7, 8;

Observation can be found that the group number = (team number - 1) >> 1;

Similarly in the second round group number = (team number - 1) >> 2;

Then the group number in the nth round=(team number-1)>>n;

Grouping is just the first step.

Next, we know that only the teams whose group numbers are adjacent to two numbers can compete (and this adjacent number is ordered, and must satisfy (a, a+1) where a is an odd number)

It should be possible to judge by parity here, but I didn't try it. Instead, another simpler trick is used: use the XOR operation to determine adjacent. (This kind of adjacency required by the XOR perfect fit problem, see the procedure for details)

The AC codes are as follows:

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
using namespace std;
double win[150][150];
double dp[10][150];
int main(void){
    int n;
    while(scanf("%d",&n)==1&&n!=-1){
        memset(dp,0,sizeof(dp)) ;
        int len=1<<n;
        for(int i=1;i<=len;i++){
            for(int j=1;j<=len;j++)
            scanf("%lf",&win[i][j]);
        }
        for(int i=0;i<=len;i++){//初始化 
            dp[0][i]=1;
        }
        for ( int i= 1 ;i<=n;i++ ){
             for ( int j= 1 ;j<=len;j++ ){
                 // Think by yourself, how to judge the match 
                for ( int k= 1 ;k<=len ;k++ ) {
                     if (((k- 1 )>>(i- 1 ))==(((j- 1 )>>(i- 1 ))^ 1 )){ // Priority link: https: //blog.csdn.net/u013630349/article/details/47444939  
                    // The displacement operation is equivalent to grouping, and the XOR operation is to judge the adjacent, and this adjacent is a regular adjacent that just meets the conditions of the title, Try writing some numbers.
                        dp[i][j]+=dp[i-1][j]*dp[i-1][k]*win[j][k];
                    }
                }
            }
        }
        double max=dp[n][1];
        int ans=1;
        for(int i=1;i<=len;i++){
            if(dp[n][i]>max){
                max=dp[n][i];
                years = i;
            }
        }
        printf("%d\n",ans);
    }
    return 0;
}

 

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324665036&siteId=291194637