Description
在
N
×
N
N×N
N×N的棋盘里面放
K
K
K个国王,使他们互不攻击,共有多少种摆放方案。国王能攻击到它上下左右,以及左上
左下右上右下八个方向上附近的各一个格子,共8个格子。
Input
只有一行,包含两个数
N
N
N,
K
K
K
(
1
<
=
N
<
=
9
,
0
<
=
K
<
=
N
∗
N
)
( 1 <=N <=9, 0 <= K <= N * N)
(1<=N<=9,0<=K<=N∗N)
Output
方案数。
Sample Input
3 2
Sample Output
16
解法:
定义
d
p
[
i
]
[
j
]
[
s
]
dp[i][j][s]
dp[i][j][s] 为当前考虑到第
i
i
i 行,已经放置了
j
j
j 个国王 且 第
i
i
i 行的状态为
s
s
s 的方案数
可以预先处理出当前行的合理方案,以及对应的棋子数
Code:
typedef long long ll;
const int MX = 1 << 9;
int cnt[MX];
ll dp[10][100][MX];
int num;
int sta[100];
bool check(int i,int j){
if(sta[i] & sta[j] || (sta[i] & (sta[j] << 1)) || (sta[i] & (sta[j] >> 1))) return false;
return true;
}
int main(){
int n,k;scanf("%d %d",&n,&k);
for(int i = 0;i < (1 << n);++i){
cnt[i] = cnt[i >> 1] + (i & 1);
}
for(int i = 0;i < (1 << n);++i){
if((i & (i << 1)) || (i & (i >> 1))) continue;
sta[num++] = i;
dp[1][cnt[i]][i] = 1;
}
for(int r = 2;r <= n;++r){
for(int i = 0;i < num;++i){//这一行的状态
for(int j = 0;j < num;++j){//上一行的状态
if(check(i,j)){
for(int t = cnt[sta[j]];t <= k;++t){
dp[r][t + cnt[sta[i]]][sta[i]] += dp[r-1][t][sta[j]];
}
}
}
}
}
ll res = 0;
for(int i = 0;i < num;++i){
res += dp[n][k][sta[i]];
}
printf("%lld\n", res);
return 0;
}