见到网上的大佬们都用了位运算。。表示看不懂就自己想了,还挺好想的(然而我不会告诉你我因为p的数组问题卡了半小时顺便D了ZZZ大佬的数据)
DP方程(伪)就是:第t轮第i个队晋级的可能=第t-1轮第i个队晋级的可能*第t-1轮第(枚举所有可以在这轮和我对战的队)队晋级的可能*战胜他的可能
所以说该怎么枚举可以在这轮和我对战的队?我们仔细研究淘汰对战表(图丑勿喷)
这里u表示在这一轮,在当前这个组里是第几个队。然后就会发现,单数组和双数组(当t=2时,3、4处于一个双数组)他要对战的队伍是不一样的,所以要分情况讨论。单数组要往下找队对战,双数组就反之。
#include<cstdio> #include<cstring> using namespace std; double p[210][210],f[20][210]; int main() {int N,n; while(scanf("%d",&N)!=EOF) { if(N==-1)break; n=1;for(int i=1;i<=N;i++)n*=2; for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) scanf("%lf",&p[i][j]); memset(f,0,sizeof(f)); for(int i=1;i<=n;i++)f[0][i]=1.0; int ln=1; for(int t=1;t<=N;t++) { int u=0,z=0; for(int i=1;i<=n;i++) { u++;if(u==ln+1){u=1;z=1-z;} if(z==0) { int end=i-u+ln; for(int j=end+1;j<=end+ln;j++) f[t][i]+=f[t-1][i]*f[t-1][j]*p[i][j]; } else { int str=i-u+1; for(int j=str-1;j>=str-ln;j--) f[t][i]+=f[t-1][i]*f[t-1][j]*p[i][j]; } } ln*=2; } int ans=0; double mmax=0; for(int i=1;i<=n;i++) if(f[N][i]>mmax) { mmax=f[N][i]; ans=i; } printf("%d ",ans); } return 0; }