http://poj.org/problem?id=3071
题目大意:一场足球淘汰赛有2^n个队伍,编号为1,2,...,2^n,按队伍编号进行比赛,每轮比赛的胜者再与对应比赛的胜者进行比赛,输掉一场比赛该队伍即被淘汰。现在给出每支队伍与其他所有队伍进行比赛胜利的概率,求最可能成为冠军的队伍编号。
在一轮比赛中某支队伍获胜的概率等于该队伍在上一轮比赛中获胜的概率与战胜本轮对手概率的乘积。所以,可以以dp[i][j]表示第i支队伍在第j轮比赛中获胜的概率,则dp[i][j] = dp[i-1][j] * sum , sum = ∑(dp[k][j-1] * m[i][k]) , 枚举出本轮所有的i可能的对手k,计算出k在上一轮比赛中获胜的概率与i战胜k的概率的乘积,全部求和得到sum,从而算出dp[i][j],
max(dp[i][n])中的i即是题目要求的解。
#include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #include <vector> #include <set> #include <map> #include <cmath> #include <queue> using namespace std; template <class T> void checkmin(T &t,T x) {if(x < t) t = x;} template <class T> void checkmax(T &t,T x) {if(x > t) t = x;} template <class T> void _checkmin(T &t,T x) {if(t==-1) t = x; if(x < t) t = x;} template <class T> void _checkmax(T &t,T x) {if(t==-1) t = x; if(x > t) t = x;} typedef pair <int,int> PII; typedef pair <double,double> PDD; typedef long long ll; #define foreach(it,v) for(__typeof((v).begin()) it = (v).begin(); it != (v).end ; it ++) const int N = 133; double p[N][N] , dp[N][8]; /* void debug(int n , int m) { puts("debug"); for(int i=0;i<m;i++) cout << dp[i][n] << endl; puts("end of debug"); } */ int main() { int n; while(~scanf("%d",&n) && n!=-1) { int m = (1 << n); for(int i=0;i<m;i++) for(int j=0;j<m;j++) scanf("%lf",&p[i][j]); for(int i=0;i<m;i++) dp[i][0] = 1; int ans; for(int i=0;i<n;i++) { ans = 0; for(int j=0;j<m;j++) { double sum = 0; for(int k=(1<<i);k<(1<<(i+1));k++) sum += dp[k^j][i] * p[j][k^j]; //cout << sum << endl; dp[j][i+1] = dp[j][i] * sum; if(dp[j][i+1] > dp[ans][i+1]) ans = j; } } printf("%d\n" , ans + 1); //debug(n , m); } return 0; }