BZOJ传送门
洛谷传送门
解析:
范围只有9,显然是状压DP。
考虑处理出每个可能的状态来减小常数。
然后枚举行,枚举当前行状态,枚举前一行状态,更新即可。
注意要预处理第一行的情况。
代码:
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define re register
#define gc getchar
#define pc putchar
#define cs const
inline int getint(){
re int num;
re char c;
while(!isdigit(c=gc()));num=c^48;
while(isdigit(c=gc()))num=(num<<1)+(num<<3)+(c^48);
return num;
}
cs int N=1<<10;
int sta[N],num[N],cnt;
ll f[10][N][200];
int n,k;
signed main(){
n=getint();
k=getint();
for(int re i=0;i<(1<<n);++i){
if(i&(i<<1))continue;
sta[++cnt]=i;
int p=i;
while(p){
p-=p&-p;
++num[cnt];
}
}
for(int re i=1;i<=cnt;++i)f[1][i][num[i]]=1;
for(int re i=2;i<=n;++i){
for(int re j=1;j<=cnt;++j){
for(int re t=1;t<=cnt;++t){
if((sta[t]&sta[j])||(sta[t]&(sta[j]<<1))||(sta[t]&(sta[j]>>1)))continue;
for(int re kkk=0;kkk<=k;++kkk)f[i][j][num[j]+kkk]+=f[i-1][t][kkk];
}
}
}
ll ans=0;
for(int re i=1;i<=cnt;++i)ans+=f[n][i][k];
cout<<ans;
return 0;
}