题目描述:

在 n×n 的棋盘上放 k 个国王,国王可攻击相邻的 8个格子,求使它们无法互相攻击的方案总数。

输入格式

共一行,包含两个整数 n和 k。

输出格式

共一行,表示方案总数,若不能够放置则输出0。

数据范围

1≤n≤10,
0≤k≤n^2

输入样例:

3 2

输出样例:

16

分析:

本题考察状态压缩DP,而且是棋盘类状压。首先,很容易想到用一串二进制数表示一行放置国王的情况,1表示放置,0表示未放置。而且由每个国王可以攻击周围的八连通区域的格子推出,每一行的状态最多会影响下一行,而不会影响下下行,这为我们逐行进行状态转移提供了可能性。首先,分析从第一行开始,逐行放置国王,如何放置是合法的。第一个条件,第i行不能有相邻两列都放了国王,设第i列的状态为st,只需要st & (st >> 1)为0就可以说明不存在相邻两列都是1了。第二个条件,根据上一行的状态如何得出下一行哪些状态是合法的。首先,第i-1行第j列放置了国王,则第i行第j列就不能放置了,即s & t要为0,其中s为i-1行的状态,t为第i行的状态;另外,上下两行对角线也不能同时为1,只需要判断s | t是否存在相邻的1即可,不存在相邻的1则说明对角线不同时为1。

状态表示:本来只需要第一维表示遍历到的行数,第二维表示第i行的状态即可,但是由于放置的国王数不能超过k,所以需要增加一维表示已经放置的国王数。故f[i][j][k]表示放完前i行的国王,一共放了j个国王且第i行状态为k的方案数。状态转移方程为f[i][j][k] = f[i][j][k] + f[i-1][j-cnt[i]][k'],其中cnt[i]表示第i行放的国王数量,k表示放置第i行前第i-1行的状态,不难理解这个状态的转移,就像01背包问题中选择第i个物品相当于f[i-1][j-v] + w一样,f[i][j][k]这个状态只要合法,方案数自然等于所有能从第i-1行的合法状态转移到f[i][j][k]状态的方案数之和。

本题并不复杂,只是稍微麻烦的是为了提高效率还需要预处理所有合法的状态,将所有不存在相邻1的合法状态都存进向量a中,并统计出每个状态包含1的数量。另外,a中的合法状态可以转移到哪些合法的状态,也可以预处理出来存进向量b中。本题方案数可能很大,需要用long long存储。

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
const int N = 12,M = 105,K = 1 << N;
long long f[N][M][K];
int n,m;
vector<int> a,cnt,b[K];
bool check(int st){return (st & (st >> 1)) == 0;
}
int count(int n){int res = 0;while(n){if(n & 1)   res++;n >>= 1;}return res;
}
int main(){cin>>n>>m;for(int i = 0;i < 1 << n;i++){if(check(i)){a.push_back(i);cnt.push_back(count(i));}   }for(int i = 0;i < a.size();i++){for(int j = 0;j < a.size();j++){int s = a[i],t = a[j];if(!(s & t) && check(s | t))   b[s].push_back(t);}}f[0][0][0] = 1;for(int i = 1;i <= n;i++){for(int j = 0;j <= m;j++){for(int k = 0;k < a.size();k++){int t = a[k];for(int s = 0;s < b[t].size();s++){int u = b[t][s];if(j >= cnt[k])    f[i][j][t] += f[i-1][j - cnt[k]][u];}}}}long long res = 0;for(int i = 0;i < a.size();i++) res += f[n][m][a[i]];cout<<res<<endl;return 0;
}

AcWing 1064 骑士相关推荐

  1. Acwing 378.骑士放置(二分图的最大独立集)

    Acwing 378.骑士放置 题意 给定一个 N×M 的棋盘,有一些格子禁止放棋子. 问棋盘上最多能放多少个不能互相攻击的骑士(国际象棋的"骑士",类似于中国象棋的"马 ...

  2. AcWing P378 骑士放置 题解

    Analysis 这道题跟前几道题差不多,依旧是匈牙利算法求二分图匹配,在连边的时候,要连两个矛盾的位置(即一个骑士和其控制的位置).然后就跑一遍匈牙利算法就好了. 1 #include<ios ...

  3. AcWing 378. 骑士放置 题解

    原题链接 题目描述 给定一个 N*M 的棋盘,有一些格子禁止放棋子. 问棋盘上最多能放多少个不能互相攻击的骑士(国际象棋的"骑士",类似于中国象棋的"马",按照 ...

  4. AcWing 378. 骑士放置(最大独立集)

    题目 给定一个 N*M 的棋盘,有一些格子禁止放棋子. 问棋盘上最多能放多少个不能互相攻击的骑士(国际象棋的"骑士",类似于中国象棋的"马",按照"日 ...

  5. Acwing 378. 骑士放置

    题目描述: 给定一个 N×M 的棋盘,有一些格子禁止放棋子. 问棋盘上最多能放多少个不能互相攻击的骑士(国际象棋的"骑士",类似于中国象棋的"马",按照&quo ...

  6. AcWing 195. 骑士精神

    双向BFS (广搜) \(O(8 ^ 7)\) 看到没有双向BFS的题解我就过来了 这道题也可以用双向\(BFS\)来做,时间复杂度与\(IDA*\)不相上下. 双向\(BFS\)的实现有多种: 把初 ...

  7. `Algorithm-Solution` `AcWing` 378. 骑士放置

    link Solution If we add the edge a−ba-ba−b where if a=(x,y)a=(x,y)a=(x,y) then bbb is the endpoint i ...

  8. 算法——AcWing算法提高课中代码和题解

    文章目录 第一章 动态规划 (完成情况:64/68) 数字三角形模型 最长上升子序列模型 背包模型 状态机模型 状态压缩DP 区间DP 树形DP 数位DP 单调队列优化DP 斜率优化DP 第二章 搜索 ...

  9. acwing提高组 第一章 动态规划

    文章目录 数字三角形模型 最长上升子序列模型 背包模型 状态机模型 状态压缩DP 区间DP 树形DP 数位DP 单调队列优化DP 斜率优化DP oj链接 数字三角形模型 AcWing 1015. 摘花 ...

最新文章

  1. value_counts()
  2. 看了这篇 LeetCode 的刷题心得,再也不用抄别人代码了
  3. 基于hsv的亮度调整算法_改变HSV的H和V部分(比如可以增加图像亮度)
  4. python中如何中止一个线程
  5. 第六章 Web开发实战1——HTTP服务
  6. Docker最全教程之Go实战,墙裂推荐(十九)
  7. dubbo和mq的使用场景
  8. Struts2之OGNL表达式语言
  9. 虚拟机本来有MySQL,后安装宝塔的MySQL导致MySQL不能启动报错
  10. 【Python 10】汇率兑换3.0(while循环)
  11. 视频分析的非局部(non-local) 神经网络模块
  12. 打印机扫描计算机远程扫描仪,未在设备上将扫描类型设置为(远程扫描仪)的解决方法...
  13. VuePress构建一个文档管理网站
  14. Mac卸载postgresql
  15. broker指定ip
  16. 计算机图形学结课论文,计算机图形学基础教程结课论文
  17. vc6.0中用GDIPlus实现加载动态gif图片(非MFC实现)
  18. oracle数据库中求某行的上一条记录和下一条记录
  19. [WebGL入门]二十六,纹理绘图
  20. 这两天净鼓捣新买的PALM680了!

热门文章

  1. LMD改进的局部均值分解matlab代码模版
  2. ajax无线遥控器,基于WiFi网络的可视化遥控搬运机器人设计
  3. tcga数据下载_使用R下载TCGA数据
  4. 南开22春学期(高起本1709、全层次1803-2103)《职场心理(麦课)》在线作业【标准答案】
  5. 年底被裁!卸磨杀驴,程序员心中的悲愤与无奈……
  6. linux psutil 监控,psutil:系统监测与进程管理
  7. Stetho、 inspect
  8. 关于网络平台建设的建议!
  9. 【Java】1-100之间所有自然数的和(while和for方法)
  10. 如何向公众号添加的京东商品链接