题目分析
这道题其实就是全概率公式的应用,可以定义状态为ans[i][j],其表示第j个队在第i轮胜出的概率,这样的话状态转移方程就很好写了。
ans[i][j]=∑ans[i−1][j]∗ans[i−1][k]∗a[j][k];
比如8个队,用2进制表示为 000, 001,010,011,100,101,110,111。于是我们会发现每一轮只需要将队伍数表示的2进制右移i-1为,并且移动完成后异或1相等的就是这一轮这个队需要面对赢得队伍,可以发现二进制还是很神奇。
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int maxn = 1<<10;
double a[maxn][maxn], ans[10][maxn];
int main(){
int n;
while(scanf("%d", &n) != EOF && n != -1){
for(int i = 0; i < (1<<n); i++)
for(int j = 0; j < (1<<n); j++)
scanf("%lf", &a[i][j]);
memset(ans, 0, sizeof(ans));
for(int i = 0; i < (1<<n); i++) ans[0][i] = 1;
for(int i = 1; i <= n; i++)
for(int j = 0; j < (1<<n); j++)
for(int k = 0; k < (1<<n); k++)
if(((j>>(i-1))^1) == (k>>(i-1))) ans[i][j] += ans[i-1][j]*a[j][k]*ans[i-1][k];
double ret = 0;
int id = 1;
for(int i = 0; i < (1<<n); i++)
if(ans[n][i] > ret){
ret = ans[n][i];
id = i+1;
}
printf("%d\n", id);
}
return 0;
}