题目大意

在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. javascript基础(完整)

    一.什么是javascript? 是一种基于对象和事件驱动(以事件驱动的方式直接对客户端的输入做出响应,无需经过服务器端)并具有安全性能的解释型脚本语言,在web应用中得到非常广泛地应用.它不需要编译 ...

  2. halcon 模板匹配 -- create_shape_model

    create_shape_model(Template : : //reduce_domain后的模板图像 NumLevels,//金字塔的层数,可设为“auto”或0—10的整数 AngleStar ...

  3. SAP computer之input and MAR

    Input and MAR Below the program counter is the input and MAR block. It includes the address and data ...

  4. JQuery特效之心形图片墙

    效果如图: 代码如下: <!doctype html> <html lang="en"> <head> <meta charset=&qu ...

  5. windows下安装Python-Whl文件

    原文链接:http://blog.sciencenet.cn/home.php?mod=space&uid=1181151&do=blog&id=865515 Note1. 整 ...

  6. Tinyxml2学习

    转自http://www.360doc.com/content/13/1223/16/3684846_339528825.shtml,尊重原文 什么是XML? XML全称EXtensible Mark ...

  7. C# 判断字符串是否左包含

    //测试字符串 左包含 //string str = "AAABBBCCC"; //char[] ss = str.ToArray(); //0-8 字符数组 //char[] s ...

  8. Js构造对象-添加方法的三种方式

    Js构造函数添加方法有多种方案,来看一个混合方式构造函数的例子:申明person构造函数,有两个属性,name,qq.在原型上添加方法showname.这是最常用的方法. <script> ...

  9. webstorm界面主题

     http://www.webstormthemes.com/ 

  10. Python—字符串+变量

    字符串转义字符格式化内建函数(后延)转义字符用一个特殊的方法表示出一系列不方便写出的内容,比如回车键,换行键,退格键借助反斜杠字符,一旦字符串中出现反斜杠,则反斜杠后面一个火几个字符表示已经不是原来的 ...