http://poj.org/problem?id=3071
题意:
有(1<<N)个人进行N次比赛,每次比赛都是第i个人和第i+1个人进行,赢的人能进入下一轮,输的人就不能继续比赛,N轮比赛之后,只会有一个人留下来,问谁最终留下来的概率最大。
思路:
概率dp,我们用dp[i][j]表示经过i场比赛之后,第j个人还没被淘汰的概率,那么状态转移方程就变成了:
dp[i][j] = sum{ dp[i-1][j] * dp[i-1][k] * P[j][k] } ,其中的k表示在第i轮有机会和i比赛的人的编号,P[j][k]表示jbeatsk的概率,最后只需要比较谁的概率最大就可以了。
代码:
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>
#define STOP() system("pause")
const int MAXN = 150 ;
int N , NN;
double P[MAXN][MAXN] ;
double dp[10][MAXN];
void solve(){
for(int i=1;i<=NN;i++)
dp[0][i] = 1 ;
for(int i=1;i<=N;i++){
int aa = 1 << (i-1) ;
for(int j=1;j<=NN;j++){
int s , e ;
s = 0 ;
int cnt = 0 ;
while( s + aa < j ) s += aa ,cnt ++ ;
if( (cnt & 1) == 0 ){
s += aa ;
e = s + aa ; s = s + 1 ;
}
else{
e = s ;
s = s - aa + 1 ;
}
dp[i][j] = 0 ;
for(int k=s;k<=NN && k<=e;k++){
dp[i][j] += dp[i-1][j] * dp[i-1][k] * P[j][k] ;
}
}
}
double _max = 0 ;
int max_num ;
for(int i=1;i<=NN;i++){
if( dp[N][i] > _max ){
_max = dp[N][i] ;
max_num = i ;
}
}
printf("%d\n",max_num);
}
int main(){
while( scanf("%d",&N)==1){
if(N == -1) break;
NN = 1 << N ;
for(int i=1;i<=NN;i++){
for(int j=1;j<=NN;j++)
scanf("%lf",&P[i][j]);
}
solve() ;
}
return 0 ;
}