题目大意:有n个选手,给你每个选手战胜另一个选手的概率。赛事为擂台战,选手1很特殊,他可以调换选手的出场顺序,使得自己的胜率最大,求1的胜率。n<=18
题解:如果由初始状态往后递推明显是不行的,因为1可以改变出场顺序状态递推太过困难(选手比赛并不是随机的),我们可以从最终状态开始倒着递推,即确定1必胜,其余状态倒着递推,最后得到都是在1必胜的前提下,dp[I][J](i为擂主,选手状态为j)的概率。
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
using namespace std;
double f[20][1<<18];
int n;
double p[20][20];
int main()
{
scanf("%d",&n);
for(int i=0;i<n;i++)
{
for(int j=0;j<n;j++)
{
scanf("%lf",&p[i][j]);
}
}
f[0][1]=1;
double tmp;
for(int i=1;i<(1<<n);i++)
{
for(int j=0;j<n;j++)
{
if(!(i&(1<<j))) continue;
for(int k=0;k<n;k++)
{
if(!(i&(1<<k))) continue;
if(j==k) continue;
double tmp=f[k][i^(1<<j)]*p[k][j]+f[j][i^(1<<k)]*p[j][k];
f[j][i]=max(f[j][i],tmp);
}
}
}
double ans=0;
for(int i=0;i<n;i++)
ans=max(ans,f[i][(1<<n)-1]);
printf("%lf",ans);
return 0;
}