展开
题目描述
在N×N的棋盘里面放K个国王,使他们互不攻击,共有多少种摆放方案。国王能攻击到它上下左右,以及左上左下右上右下八个方向上附近的各一个格子,共8个格子。
注:数据有加强
输入格式
只有一行,包含两个数N,K ( 1 <=N <=9, 0 <= K <= N * N)
输出格式
所得的方案数
输入
3 2
输出
16
一道入门级别的状压DP
#include<bits/stdc++.h>
using namespace std;
int n,k;
int cnt=0;
const int maxn=2005;
long long sumKing[maxn];
long long ez[maxn];//二进制表示每一行的位置放不放king
long long dp[12][maxn][105];
void dfs(int x,int num,int cur)
{
if(cur>=n){
sumKing[++cnt]=num;
ez[cnt]=x;
return ;
}
dfs(x,num,cur+1);//不选当前的king
dfs(x+(1<<cur),num+1,cur+2);//选当前的king,则后一个不能选了
}
int main()
{
cin>>n>>k;
dfs(0,0,0);//枚举每一行的所有可行状态
//这个for循环是一行一行寻找符合的状态
for(int i=1;i<=cnt;i++){
dp[1][i][sumKing[i]]=1;
}
for(int i=1;i<=n;i++){
for(int j=1;j<=cnt;j++){
for(int l=1;l<=cnt;l++){
if(ez[l]&ez[j]) continue;
if((ez[l]<<1)&ez[j]) continue;
if(ez[l]&(ez[j]<<1)) continue;
for(int p=sumKing[l];p<=k;p++){
dp[i][l][p]+=dp[i-1][j][p-sumKing[l]];
}
}
}
}
long long ans=0;
for(int i=1;i<=cnt;i++){
ans+=dp[n][i][k];
}
cout<<ans<<endl;
return 0;
}