题目描述
在N×N的棋盘里面放K个国王,使他们互不攻击,共有多少种摆放方案。国王能攻击到它上下左右,以及左上左下右上右下八个方向上附近的各一个格子,共8个格子。
注:数据有加强(2018/4/25)
输入输出格式
输入格式:
只有一行,包含两个数N,K ( 1 <=N <=9, 0 <= K <= N * N)
输出格式:
所得的方案数
输入输出样例
输入样例#1:
3 2
输出样例#1:
16
解释:状态压缩dp,dp[i][j][k]:第1-i行,且第i行状态为j,总共个数为k的方案数多少,然后直接计算就好了
#include<iostream>
using namespace std;
long long dp[12][(1<<9)+10][100];
int n=0,k=0;
bool check(long long x){
int f=0;
while(x){
if((x&1)&&f) return 0;
f=x&1;x>>=1;
}
return 1;
}
int num(long long x){
int sum=0;
while(x){
if(x&1) sum++;
x>>=1;
}
return sum;
}
bool judge(int x,int y){
if(x&y) return 0;
if((x<<1)&y) return 0;
if(x&(y<<1)) return 0;
return 1;
}
int main(){
ios::sync_with_stdio(false);
cin>>n>>k;
for(int i=0;i<(1<<n);i++) if(check(i)&&num(i)<=k) dp[1][i][num(i)]++;
for(int i=2;i<=n;i++){
for(int j=0;j<(1<<n);j++){
if(!check(j)) continue;
for(int u=0;u<(1<<n);u++){
if(!check(u)) continue;
if(!judge(u,j)) continue;
for(int v=0;v<=k;v++){
if(v+num(j)<=k) dp[i][j][v+num(j)]+=dp[i-1][u][v];
}
}
}
}
long long ret=0;
for(int i=0;i<(1<<n);i++){
if(check(i)) ret+=dp[n][i][k];
}
cout<<ret<<endl;
return 0;
}