poj 3701 Football (概率+dp)
题目链接:http://poj.org/problem?id=3071
大致题意:共有2^n个球队,采用单向淘汰的形式进行比赛,即1队和2队进行1场比赛,3队和4队进行1场比赛,依次类推,胜者进入下一轮,比赛安排同上。这样只进行N轮就可以确定冠军。现在告诉你第i支球队战胜第j支球队的胜率矩阵,求最可能夺冠的队伍是哪支。
Time Limit: 1000MSMemory Limit: 65536K
样例:
Sample Input
2 0.0 0.1 0.2 0.3 0.9 0.0 0.4 0.5 0.8 0.6 0.0 0.6 0.7 0.5 0.4 0.0 -1
Sample Output
2
思路:题目下方给出的Hint基本就是题解:
所以很容易想到第i支球队在第j轮中获胜的概率应该是:
dp[i][j]= ∑ dp[i][j-1]*dp[k][j-1]*Matrix[i][k] k是第i支球队可能的对手
那么k的取值应该怎样找?首先第j轮,第i支球队可能的对手有2^(j-1)个,如果将比赛画成一颗树,2^n支球队是根节点,那么这2^(j-1)支球队就是i节点的兄弟节点所对应的所有根节点。
1 #include<cstdio> 2 #include<cstring> 3 #include<cmath> 4 const int MAXNUM=150; 5 double map[MAXNUM][MAXNUM]; 6 double dp[MAXNUM][10]; 7 int n; 8 int main(){ 9 int i,j,k; 10 while(scanf("%d",&n)&&(n!=-1)){ 11 memset(dp,0,sizeof(dp)); 12 for(i=0;i<MAXNUM;i++)dp[i][0]=1; 13 int num=1<<n; //共有2^n支队伍 14 for(i=0;i<num;i++){ 15 for(j=0;j<num;j++){ 16 scanf("%lf",&map[i][j]); 17 } 18 } 19 for(j=1;j<=n;j++){ 20 for(i=0;i<num;i++){ 21 int step=1<<(j-1); //可能对手的个数 22 int start=i/step; 23 if(start%2)start--; //寻找兄弟节点 24 else start++; 25 start*=step; 26 for(k=start;k<start+step;k++){ 27 dp[i][j]+=dp[i][j-1]*dp[k][j-1]*map[i][k]; 28 } 29 30 } 31 } 32 double max=dp[0][n]; 33 int win=0; 34 for(i=1;i<num;i++){ 35 if(dp[i][n]>max){ 36 max=dp[i][n]; 37 win=i; 38 } 39 } 40 printf("%d\n",win+1); 41 } 42 return 0; 43 }