P1896 互不侵犯
题面:https://www.luogu.org/problemnew/show/P1896
经典的状压dp,dp方程:f[i][j][k]+=f[i-1][j-num[k]][l];
还有位运算的判断也很重要
Code:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<cstdlib>
#include<algorithm>
#include<bitset>
#include<ctime>
#include<stack>
using namespace std;
const int N=10005,M=15;
long long n,k1,num[N],s[N],f[M][M][N],tot,ans;
long long lowbit(long long x){
return x&(-x);
}
int main(){
scanf("%lld%lld",&n,&k1);
for(int i=0;i<(1<<n);i++){
if(!(i&(i<<1))){
int sum=0,t=i;
++tot;
while(t){
t-=lowbit(t);
++sum;
}
num[tot]=sum;
s[tot]=i;
}
}
for(int i=1;i<=tot;i++){
if(num[i]>k1)
continue;
f[1][num[i]][i]=1;
}
for(int i=2;i<=n;i++){
for(int j=0;j<=k1;j++){
for(int k=1;k<=tot;k++){
if(num[k]>j)
continue;
for(int l=1;l<=tot;l++){
if(num[l]>j-num[k])
continue;
if(s[k]&s[l])
continue;
if(s[k]&(s[l]<<1))
continue;
if(s[l]&(s[k]<<1))
continue;
f[i][j][k]+=f[i-1][j-num[k]][l];
}
}
}
}
for(int j=1;j<=tot;j++){
ans+=f[n][k1][j];
}
printf("%lld\n",ans);
return 0;
}