AcWing 1064 骑士
题目描述:
在 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 骑士相关推荐
- Acwing 378.骑士放置(二分图的最大独立集)
Acwing 378.骑士放置 题意 给定一个 N×M 的棋盘,有一些格子禁止放棋子. 问棋盘上最多能放多少个不能互相攻击的骑士(国际象棋的"骑士",类似于中国象棋的"马 ...
- AcWing P378 骑士放置 题解
Analysis 这道题跟前几道题差不多,依旧是匈牙利算法求二分图匹配,在连边的时候,要连两个矛盾的位置(即一个骑士和其控制的位置).然后就跑一遍匈牙利算法就好了. 1 #include<ios ...
- AcWing 378. 骑士放置 题解
原题链接 题目描述 给定一个 N*M 的棋盘,有一些格子禁止放棋子. 问棋盘上最多能放多少个不能互相攻击的骑士(国际象棋的"骑士",类似于中国象棋的"马",按照 ...
- AcWing 378. 骑士放置(最大独立集)
题目 给定一个 N*M 的棋盘,有一些格子禁止放棋子. 问棋盘上最多能放多少个不能互相攻击的骑士(国际象棋的"骑士",类似于中国象棋的"马",按照"日 ...
- Acwing 378. 骑士放置
题目描述: 给定一个 N×M 的棋盘,有一些格子禁止放棋子. 问棋盘上最多能放多少个不能互相攻击的骑士(国际象棋的"骑士",类似于中国象棋的"马",按照&quo ...
- AcWing 195. 骑士精神
双向BFS (广搜) \(O(8 ^ 7)\) 看到没有双向BFS的题解我就过来了 这道题也可以用双向\(BFS\)来做,时间复杂度与\(IDA*\)不相上下. 双向\(BFS\)的实现有多种: 把初 ...
- `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 ...
- 算法——AcWing算法提高课中代码和题解
文章目录 第一章 动态规划 (完成情况:64/68) 数字三角形模型 最长上升子序列模型 背包模型 状态机模型 状态压缩DP 区间DP 树形DP 数位DP 单调队列优化DP 斜率优化DP 第二章 搜索 ...
- acwing提高组 第一章 动态规划
文章目录 数字三角形模型 最长上升子序列模型 背包模型 状态机模型 状态压缩DP 区间DP 树形DP 数位DP 单调队列优化DP 斜率优化DP oj链接 数字三角形模型 AcWing 1015. 摘花 ...
最新文章
- value_counts()
- 看了这篇 LeetCode 的刷题心得,再也不用抄别人代码了
- 基于hsv的亮度调整算法_改变HSV的H和V部分(比如可以增加图像亮度)
- python中如何中止一个线程
- 第六章 Web开发实战1——HTTP服务
- Docker最全教程之Go实战,墙裂推荐(十九)
- dubbo和mq的使用场景
- Struts2之OGNL表达式语言
- 虚拟机本来有MySQL,后安装宝塔的MySQL导致MySQL不能启动报错
- 【Python 10】汇率兑换3.0(while循环)
- 视频分析的非局部(non-local) 神经网络模块
- 打印机扫描计算机远程扫描仪,未在设备上将扫描类型设置为(远程扫描仪)的解决方法...
- VuePress构建一个文档管理网站
- Mac卸载postgresql
- broker指定ip
- 计算机图形学结课论文,计算机图形学基础教程结课论文
- vc6.0中用GDIPlus实现加载动态gif图片(非MFC实现)
- oracle数据库中求某行的上一条记录和下一条记录
- [WebGL入门]二十六,纹理绘图
- 这两天净鼓捣新买的PALM680了!