#zYDPybttg050401. 1592:【例 1】国王

1592:【例 1】国王

好的,我将这道题整理为清晰的题面格式,并补充样例解释、数据范围与时空限制:


题目描述

原题来自:SGU 223

n×nn \times n 的棋盘上放 kk 个国王,国王可攻击相邻的 88 个格子(即上下左右和四个对角方向),求使它们无法互相攻击的方案总数。


输入格式

只有一行,包含两个整数 nnkk


输出格式

输出一行,为方案总数,若不能够放置则输出 00


样例

样例输入 1

3 2

样例输出 1

16

样例解释 1

n=3n=3,棋盘 3×33\times 3,放置 k=2k=2 个国王,要求国王之间不能攻击。

我们可以枚举所有放置方案,计算总数为 1616

具体验证:对于 3×33\times 3 棋盘,放置两个国王且不相互攻击的方案共 1616 种(可通过搜索或状态压缩 DP 计算得到)。


样例输入 2

4 4

样例输出 2

79

数据范围

对于全部数据:

  • 1n101 \le n \le 10
  • 0kn20 \le k \le n^2

时空限制

  • 时间:500 ms500 \text{ ms}
  • 内存:65536 KB65536 \text{ KB}(注意此题内存限制较小,为 64 MB)

提示
此题为 状态压缩 DP(状压 DP)经典题。

状态设计

  • 用二进制数表示一行的国王放置情况:11 表示放国王,00 表示不放;
  • 状态必须满足:一行内不能有相邻的国王(即二进制数中不能有两个连续的 11);
  • 相邻两行之间,上一行的状态 s1s1 和下一行的状态 s2s2 必须满足:
    1. s1s1s2s2 不能在同一列有国王(即 s1&s2=0s1 \& s2 = 0);
    2. s1s1s2s2 的国王不能在相邻列(即 (s11)&s2=0(s1 \ll 1) \& s2 = 0(s11)&s2=0(s1 \gg 1) \& s2 = 0)。

dp[i][j][s]dp[i][j][s] 表示前 ii 行,已经放置了 jj 个国王,且第 ii 行的状态为 ss 的方案数。

转移方程:

$$dp[i][j][s] = \sum_{s'} dp[i-1][j - \text{popcount}(s)][s']$$

其中 ss' 是第 i1i-1 行的状态,且 ssss' 满足上述条件。

初始化:dp[0][0][0]=1dp[0][0][0] = 1

最终答案:

ans=sdp[n][k][s]\text{ans} = \sum_{s} dp[n][k][s]

优化

  • 预处理所有合法行状态(一行内不相邻)及该状态的国王数 popcount(s)\text{popcount}(s)
  • 预处理状态间的兼容性(两行不攻击)。

复杂度:O(n×k×S2)O(n \times k \times |S|^2),其中 S|S| 是合法行状态数,对于 n10n \le 10S144|S| \le 144,可以接受。