题目大意

在N×N的棋盘里面放K个国王,使他们互不攻击,共有多少种摆放方案。国王能攻击到它上下左右,以及左上左下右上右下八个方向上附近的各一个格子,共8个格子。( 1 <=N <=9, 0 <= K <= N * N)

题解

这跟“炮兵阵地”很是相似。定义一行的状态\(S\)为是否安放国王的01集合。先预处理出一行中两两国王无法攻击的所有状态(以后简称合理状态),以及这些状态中1的个数\(g(S)\)。定义\(f(r,S,k)\)为当第\(r\)行的状态为\(S\)时,1至\(r\)行中存在\(k\)个国王的安排有多少种。则递归式为:

\[f(r,S,k)=\sum_{S'\And(S|(S<<1)|(S>>1))=0}f(r-1,S',k-g(S))
\]

实际上,S用可行状态的编号表示即可。

注意

  • f数组中用来存放S的大小应当是1<<MAX_N,而不是MAX_N,因为合理状态的数量可能比N多,最大编号也就比N多了。
  • 注意递归式中与\(S'\)与操作的还有\(S\)。
  • 最后统计结果时,枚举S的终止条件为达到最大合理状态的编号,而不是N。注意下定义。

关于暴力

一个一个枚举国王可能在的位置。因为重合子问题\(f(r,S,k)\)被计算了多次,故不是正解。但是要做到正确,注意:

  • 用来恢复现场的数据应当保存在系统栈内,而不是放在堆中供多次递归函数共用。这就错了。
  • 仔细检查,防止手误。

AC代码:

#include <cstdio>
#include <cstring>
#include <bitset>
#include <iostream>
using namespace std; #define ll long long const int MAX_N = 10, MAX_K = 100;
ll F[MAX_N][1<<MAX_N][MAX_K];
int States[1<<MAX_N], State1Cnt[1<<MAX_N];
int N, StCnt, K; void GetProperState(int n)
{
StCnt = 0;
for (int i = 0; i <= ~(~1 << n - 1); i++)
{
if (!(i << 1 & i))
{
States[StCnt] = i;
int temp = i;
while (temp)
{
if (temp & 1)
State1Cnt[StCnt]++;
temp >>= 1;
}
StCnt++;
}
}
} void PrintBinary(ll x)
{
cout << bitset<5>(x);
} ll DP()
{
ll ans = 0;
for (int i = 0; i <= StCnt; i++)
F[0][i][State1Cnt[i]] = 1;
for (int level = 1; level < N; level++)
for (int i = 0; i < StCnt; i++)
for (int j = 0; j < StCnt; j++)
if (!(States[i]&States[j])&&!((States[i] << 1) & States[j]) && !((States[i] >> 1) & States[j]))
for (int k = State1Cnt[i]; k <= K; k++)
F[level][i][k] += F[level - 1][j][k - State1Cnt[i]];
for (int i = 0; i < StCnt; i++)
ans += F[N - 1][i][K];
return ans;
} int main()
{
scanf("%d%d", &N, &K);
GetProperState(N);
printf("%lld\n", DP());
return 0;
}

luogu1896 [SCOI2005]互不侵犯 状压DP的更多相关文章

  1. BZOJ1087[SCOI2005]互不侵犯——状压DP

    题目描述 在N×N的棋盘里面放K个国王,使他们互不攻击,共有多少种摆放方案.国王能攻击到它上下左右,以及左上左下右上右下八个方向上附近的各一个格子,共8个格子. 输入 只有一行,包含两个数N,K ( ...

  2. P1896 [SCOI2005]互不侵犯 状压dp

    正解:状压dp 解题报告: 看到是四川省选的时候我心里慌得一批TT然后看到难度之后放下心来觉得大概没有那么难 事实证明我还是too young too simple了QAQ难到爆炸TT我本来还想刚一道 ...

  3. SCOI2005 互不侵犯 [状压dp]

    题目传送门 题目大意:有n*n个格子,你需要放置k个国王使得它们无法互相攻击,每个国王的攻击范围为上下左走,左上右上左下右下,共8个格子,求最多的方法数 看到题目,是不是一下子就想到了玉米田那道题,如 ...

  4. [SCOI2005]互不侵犯 (状压$dp$)

    题目链接 Solution 状压 \(dp\) . \(f[i][j][k]\) 代表前 \(i\) 列中 , 已经安置 \(j\) 位国王,且最后一位状态为 \(k\) . 然后就可以很轻松的转移了 ...

  5. NOI P1896 互不侵犯 状压DP

    题目描述 在N×N的棋盘里面放K个国王,使他们互不攻击,共有多少种摆放方案.国王能攻击到它上下左右,以及左上左下右上右下八个方向上附近的各一个格子,共8个格子. 注:数据有加强(2018/4/25) ...

  6. _bzoj1087 [SCOI2005]互不侵犯King【dp】

    传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=1087 令f(i, j, k)表示前i列,二进制状态为j,已经用了k个国王的方案数,则 f(i ...

  7. 洛谷——P1896 [SCOI2005]互不侵犯

    P1896 [SCOI2005]互不侵犯 状压DP入门题 状压DP一般需要与处理状态是否合法,节省时间 设定状态dp[i][j][k]表示第i行第j个状态选择国王数为k的方案数 $dp[i][j][n ...

  8. 状压DP概念 及例题(洛谷 P1896 互不侵犯)

    状压DP 就是状态压缩DP.所谓状态压缩,就是将一些复杂的状态压缩起来,一般来说是压缩为一个二进制数,用01来表示某一元素的状态. 比如一排灯泡(5个) 我们可以用一串二进制01串来表示他们的状态 1 ...

  9. BZOJ 1087: [SCOI2005]互不侵犯King [状压DP]

    1087: [SCOI2005]互不侵犯King Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 3336  Solved: 1936[Submit][ ...

随机推荐

  1. 每日算法——新型在线LCA

    在线LCA一般大家都会用倍增吧,时间复杂度O(nlogn),空间复杂度O(nlogn),都是非常严格的复杂度限制,并且各种边界处理比较麻烦,有没有更快更好的办法呢? 我们发现,在树链剖分时,我们不经意 ...

  2. 【JAVA练习】- 给定精度求圆周率π

    给定一个精度求圆周率π的近似值 给定公式:π/4=1-1/3+1/5-1/7+1/9-... public static void main(String[] args) { System.out.p ...

  3. 浏览器缓存机制(HTTP缓存机制)

    其机制是根据HTTP报文的缓存标识进行的. 过程:浏览器发起HTTP请求 – 服务器响应该请求.那么浏览器第一次向服务器发起该请求后拿到请求结果,会根据响应报文中HTTP头的缓存标识,决定是否缓存结果 ...

  4. js-常见简单的js判断方法(暂不参考正则)

    1: 2: 3: 4: 5: 6: 7:

  5. 【PostgreSQL-9.6.3】表继承

    表继承是PostgreSQL特有的,子表可以从父表中继承字段和一些属性.例如: --创建一张表“persons”作为父表: test=# create table persons ( test(# i ...

  6. C# 查找、结束进程 - 通过进程名精确、模糊查找、结束进程

    /// <summary> /// 根据“精确进程名”结束进程 /// </summary> /// <param name="strProcName" ...

  7. Deutsch lernen (14)

    1.    das Abseits, -  越位 Der Linienrichter winkte Abseits.  winken - winkte - gewunken  示意 2.    abs ...

  8. change project compliance and jre to 1.5

    这个主要检查一下几点 项目的jdk为1.7 java版本设置为1.7 java compiler 的页面设置为以下,并且去掉勾选java compiler 下面的 enableproject spec ...

  9. brew 安装的.net 运行时提示"Did you mean to run dotnet SDK commands?"

    原因未知,但有解决方案 使用 brew cask 安装的.NET Core brew cask install dotnet 结果运行时出现: 解决方案: 下载官方 .pkg 文件安装,顺便卸载掉 b ...

  10. Apex语言(八)类和对象

    1.类和对象 一切皆对象,是客观存在的万物,有标识.属性和行为.一个人,一台电脑,一辆轿车都是对象 类是创建对象的模板或蓝图,是对象的抽象,是对象的类型. 一个对象是一个类的一个实例,是一个类的变量. ...