【Codeforces 678E】【JZOJ 4648】锦标赛

来源:互联网 发布:java不关闭流 编辑:程序博客网 时间:2024/05/17 18:47

Description

403机房最近决定举行一场锦标赛。锦标赛共有N个人参加,共进行N-1轮。第一轮随机挑选两名选手进行决斗,胜者进入下一轮的比赛,第二轮到第N-1轮再每轮随机挑选1名选手与上一轮胜利的选手决斗,最后只剩一轮选手。第i名选手与第j名选手决斗,第i名选手胜利的概率是a[i][j].
作为一号选手的富榄想知道如何安排每轮出场的选手可以使得他获胜的概率最大,并求出这个最大概率。
对于100%的数据,N<=18

Analysis

这题,1.可以从活的推成死的,2.可以从死的推成活的;3.可以从当前推到未来,4.可以从过去推到当前。
但是,这两两组合中,只有从过去推到当前同时从死的推成活的才能满足题意,也即同时满足2&4才能满足题意,为什么呢?
若从活的推到死的,则状态会变成胜负两种,无法统计答案。
反过来呢,最后的状态只有富榄一个人活着,那我们从其他人死的推成活的,合并状态。
所以不能有1
若是2&3,你怎么知道一开始是谁当擂主?又要枚举吗?TLE
所以我们按照2&4的方法DP。

Code

#include<cstdio>#include<algorithm>#define fo(i,a,b) for(int i=a;i<=b;i++)#define wengwentao_Orz 1using namespace std;typedef double db;const int N=19;int n,_2[N];db a[N][N],f[1<<N][N];int main(){    scanf("%d",&n);    _2[0]=1;    fo(i,1,n) _2[i]=_2[i-1]*2;    fo(i,0,n-1)        fo(j,0,n-1) scanf("%lf",&a[i][j]);    f[wengwentao_Orz][0]=1;    for(int s=3;s<_2[n];s+=2)        fo(i,0,n-1)            if(s&_2[i])                fo(j,0,n-1)                    if(i!=j && s&_2[j]) f[s][i]=max(f[s][i],f[s^_2[j]][i]*a[i][j]+f[s^_2[i]][j]*a[j][i]);    db ans=0;    fo(i,0,n-1) ans=max(ans,f[_2[n]-1][i]);    printf("%.7lf",ans);    return 0;}
0 0
原创粉丝点击