【JZOJ4648】锦标赛
Description
403机房最近决定举行一场锦标赛。锦标赛共有N个人参加,共进行N-1轮。第一轮随机挑选两名选手进行决斗,胜者进入下一轮的比赛,第二轮到第N-1轮再每轮随机挑选1名选手与上一轮胜利的选手决斗,最后只剩一轮选手。第i名选手与第j名选手决斗,第i名选手胜利的概率是
ai,j
.
作为一号选手的富榄想知道如何安排每轮出场的选手可以使得他获胜的概率最大,并求出这个最大概率。
原题在:CF678E
这谁翻译的?
Solution
这里%%% 32 FL。
N那么小,显然状压dp。
顺着从全部人存活推到只剩FL是不行的(一个状态会推到多个状态)。
于是我们从只有FL到复活所有人。
我们设
FS,i
表示当前存活人的集合为
S
,
FS,i=FS−2j−1,i∗ai,j+FS−2i−1,j∗aj,i(i,j∈S)
边界条件为: F1,1=1
Code
#include<iostream>
#include<cstdio>
#include<cstdlib>
#define fo(i,j,k) for(int i=j;i<=k;i++)
#define fd(i,j,k) for(int i=j;i>=k;i--)
#define N 19
#define M 270000
using namespace std;
double a[N][N];
bool bz[N];
int b[N];
double f[M][N];
int n;
int main()
{
cin>>n;
fo(i,1,n)
fo(j,1,n) scanf("%lf",&a[i][j]);
f[1][1]=1;
fo(s,3,(1<<n)-1)
fo(i,1,n)
if(s&(1<<i-1))
fo(j,1,n)
if(s&(1<<j-1) && i!=j)
f[s][i]=max(f[s][i],f[s-(1<<j-1)][i]*a[i][j]+f[s-(1<<i-1)][j]*a[j][i]);
double ans=0;
fo(i,1,n) ans=max(ans,f[(1<<n)-1][i]);
printf("%.7lf",ans);
}