互不侵犯(luogu 1896)
题目描述
在N×N的棋盘里面放K个国王,使他们互不攻击,共有多少种摆放方案。国王能攻击到它上下左右,以及左上左下右上右下八个方向上附近的各一个格子,共8个格子。
注:数据有加强(2018/4/25)
输入输出格式
输入格式:
只有一行,包含两个数N,K ( 1 <=N <=9, 0 <= K <= N * N)
输出格式:
所得的方案数
输入输出样例
第一篇状压,好开心~
虽然数据点很小,但数据量可非常大,注意开long long
code
#include<stdio.h>
#include<algorithm>
using namespace std;
int n,m,cnt,cas[1000];
long long f[10][1000][1000],num[1000];
int getsum(int x) {
int re=0;
while(x) re+=(x&1),x>>=1;
return num[cnt]=re;
}
int main()
{
scanf("%d%d",&n,&m);
int mx=(1<<n)-1;
for(int i=0;i<=mx;++i) if(!((i<<1)&i)) {
cas[++cnt]=i;
f[1][cnt][getsum(i)]=1;
}
for(int i=2;i<=n;++i) {
for(int j=1;j<=cnt;++j) {
int x=cas[j];
for(int k=1;k<=cnt;++k) {
int y=cas[k];
if(x&y || x&(y>>1) || x&(y<<1)) continue;
for(int l=0;l<=m;++l) f[i][j][num[j]+l]+=f[i-1][k][l];
}
}
}
long long ans=0;
for(int i=1;i<=cnt;++i) ans+=f[n][i][m];
printf("%lld",ans);
return 0;
}
从0到1很难,但从1到100很容易