n,k,p[89],P,Cnt[89],l[89],Link[89][89];
long int f[2][82][89],Ans;
void init(r,c,d){
if(d>=n){p[P]=r,Cnt[P++]=c;return;}
init(r,c,d+1),init(r|1<<d,c+1,d+2);
}
main(F){
scanf("%d%d",&n,&k);
init(0,0,0),*l=1;
for(int i=0;i<P;++i)
for(int j=i+1;j<P;++j)
if(!(p[j]&(p[i]|(p[i]<<1)|(p[i]>>1))))
Link[i][l[i]++]=j,Link[j][l[j]++]=i;
for(int i=0;i<P;++i)
++f[0][Cnt[i]][i];
for(--n;n--;F=!F){
memset(f[F],0,sizeof f[F]);
for(int S=0;S<P;++S)
for(int K=k;K>=Cnt[S];--K) //here
for(int s=0;s<l[S];++s)
f[F][K][S]+=f[!F][K-Cnt[S]][Link[S][s]];
}
for(int i=0;i<P;++i)
Ans+=f[!F][k][i];
printf("%ld",Ans);
}
刚开始:35ms。可是发现还能再优化:32ms-604kb
。感觉还没有到极限,再优化些内存:32ms-568kb。这时候,我看了看大家的提交记录,发现这份代码竟然只能排在最优解第 10 页!做了半天的结果,怎么能这样!那就再做半天吧(bushi 于是我结合了两位dalao的思路,写出了30ms-680kb。问题来了,我发现转移方程
fi,K,S=∑fi−1,K−Cnts,s([Compatible(S,s)])
中第i行仅和i-1行相关,于是联想到滚动数组。可是总是对不了。过了好一会儿才发觉:每次滚动前要清空数组!之前一直忘了清零。这样,有了最终成果:
30ms-612kb,也就是上述的代码。这份代码汇集了两位提交记录中大佬的思想和我这个蒟蒻的菜鸡想法(大佬dd我),各位看个乐子就行。