Luogu P5005 中国象棋 - 摆上马 / Luogu P8756 国际象棋 题解 [ 蓝 ] [ 状压 dp ] [ 位运算 ]
国际象棋:模板棋盘状压。
摆上马:需要点思维的棋盘状压,相比上一道题加了“蹩马脚”的设定。
Easy_version :国际象棋
概述一下此类棋盘问题的思路:
- 用二进制数表示出棋盘上某一行的状态。
- 用位运算预处理出合法的单行状态,以及需要用到的一些东西。
- 用位运算判断前一行或者前几行能否转移过来。
- 转移前一行或者前几行的兼容类。
基础位运算
判断两边是否有:i&(i>>1) 和 i&(i<<1) 。
判断 \(i\) 是否包含在合法状态 \(j\) 里: (i&j)==i 。
对于本题
记录下两行的状态,定义 \(dp[i][j][k][l]\) 表示第 \(i\) 行时,第 \(i\)行状态为 \(j\) ,第 \(i-1\) 行状态为 \(k\) ,且目前摆了 \(l\) 个马的方案数。
初始化 \(dp[0][0][0][0]=1\) 。
循环顺序是:
- 行数。
- 马的个数。
- 第 \(i\) 行状态。
- 第 \(i-1\) 行状态。
- 第 \(i-2\) 行状态。
注意由于只会用到前一行的状态,所以我们可以强行滚动数组优化,通过 \(\bmod 2\) 来解决。滚动数组每次必须先初始化为 \(0\) 。
时间复杂度 \(O(2^{3n}mk)\),有点紧,常数不能太大。
为了不在最后统计一遍,太过麻烦,所以我们多加了两行,并强制这两行必须不能放马,这样就不用手工统计方案数了。
代码
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> pi;
int n,m,k,tot[70];
const ll mod=1e9+7;
ll dp[2][70][70][25];
int main()
{
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
cin>>n>>m>>k;
for(int i=0;i<(1<<n);i++)
{
for(int j=0;j<n;j++)
{
tot[i]+=((i>>j)&1);
}
}
dp[0][0][0][0]=1;
for(int i=1;i<=m+2;i++)
{
for(int j=0;j<=k;j++)
{
for(int a=0;a<(1<<n);a++)
{
for(int b=0;b<(1<<n);b++)
{
dp[i&1][a][b][j]=0;
if(((a>>2)&b)||((a<<2)&b))continue;
for(int c=0;c<(1<<n);c++)
{
if(((a>>1)&c)||((a<<1)&c))continue;
if(tot[a]<=j)
{
dp[i&1][a][b][j]=(dp[i&1][a][b][j]+dp[(i&1)^1][b][c][j-tot[a]])%mod;
}
}
}
}
}
}
cout<<dp[(m+2)&1][0][0][k];
return 0;
}
Hard_version :中国象棋 - 摆上马
相比上一道,这道必须考虑蹩马脚的情况,且不用记录马的个数。
这题难点便是在判断蹩马脚:
进阶位运算
筛选出本行左边是 \(0\) ,这一位是 \(1\) 的点: i&((~i)>>1) 。
筛选出本行右边是 \(0\) ,这一位是 \(1\) 的点: i&((~i)<<1) 。
考虑 \(i\) 和 \(i-1\) 行时
\(a\) 为第 \(i\) 行状态,\(b\) 为第 \(i-1\) 行状态,\(c\) 为第 \(i-2\) 行状态。
第 \(i\) 行左边没有蹩马脚,并且可以攻击到左上的马的情况:a&((~a)>>1)&(b>>2) 。
第 \(i\) 行右边没有蹩马脚,并且可以攻击到右上的马的情况:a&((~a)<<1)&(b<<2) 。
第 \(i-1\) 行左边没有蹩马脚,并且可以攻击到左下的马的情况:b&((~b)>>1)&(a>>2) 。
第 \(i-1\) 行右边没有蹩马脚,并且可以攻击到右下的马的情况:b&((~b)<<1)&(a<<2) 。
考虑 \(i\) 和 \(i-2\) 行时
第 \(i\) 行上边没有蹩马脚,并且可以攻击到左上的马的情况:a&(~b)&(c>>1) 。
第 \(i\) 行上边没有蹩马脚,并且可以攻击到右上的马的情况:a&(~b)&(c<<1) 。
第 \(i-2\) 行下边没有蹩马脚,并且可以攻击到左下的马的情况:c&(~b)&(a>>1) 。
第 \(i-2\) 行下边没有蹩马脚,并且可以攻击到右下的马的情况:c&(~b)&(a<<1) 。
时间复杂度 \(O(2^{3y}x)\) 。
代码
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> pi;
int n,m;
const ll mod=1e9+7;
ll dp[2][70][70];
int main()
{
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
cin>>m>>n;
dp[0][0][0]=1;
for(int i=1;i<=m+2;i++)
{
for(int a=0;a<(1<<n);a++)
{
for(int b=0;b<(1<<n);b++)
{
dp[i&1][a][b]=0;
if((a&((~a)>>1)&(b>>2))||((a&((~a)<<1)&(b<<2)))||(b&((~b)>>1)&(a>>2))||(b&((~b)<<1)&(a<<2)))continue;
for(int c=0;c<(1<<n);c++)
{
if(((~b)&a&(c>>1))||((~b)&a&(c<<1))||((~b)&c&(a<<1))||((~b)&c&(a>>1)))continue;
dp[i&1][a][b]=(dp[i&1][a][b]+dp[(i&1)^1][b][c])%mod;
}
}
}
}
cout<<dp[(m+2)&1][0][0];
return 0;
}
Luogu P5005 中国象棋 - 摆上马 / Luogu P8756 国际象棋 题解 [ 蓝 ] [ 状压 dp ] [ 位运算 ]的更多相关文章
- BZOJ 4042 Luogu P4757 [CERC2014]Parades (树形DP、状压DP)
题目链接 (BZOJ) https://www.lydsy.com/JudgeOnline/problem.php?id=4042 (Luogu) https://www.luogu.org/prob ...
- [Luogu P3959] 宝藏 (状压DP+枚举子集)
题面 传送门:https://www.luogu.org/problemnew/show/P3959 Solution 这道题的是一道很巧妙的状压DP题. 首先,看到数据范围,应该状压DP没错了. 根 ...
- [Luogu P2831] 愤怒的小鸟 (状压DP)
题面: 传送门:https://www.luogu.org/problemnew/show/P2831 Solution 首先,我们可以先康一康题目的数据范围:n<=18,应该是状压或者是搜索. ...
- FZU 1025 状压dp 摆砖块
云峰菌曾经提到过的黄老师过去讲课时的摆砖块 那时百度了一下题目 想了想并没有想好怎么dp 就扔了 这两天想补动态规划知识 就去FZU做专题 然后又碰到了 就认真的想并且去做了 dp思想都在代码注释里 ...
- 状压DP之中国象棋
题目 传送们 这次小可可想解决的难题和中国象棋有关,在一个N行M列的棋盘上,让你放若干个炮(可以是0个),使得没有一个炮可以攻击到另一个炮,请问有多少种放置方法.大家肯定很清楚,在中国象棋中炮的行走方 ...
- 状压dp:luogu P2704 [NOI2001]炮兵阵地
https://www.luogu.org/problemnew/show/P2704 知识点:1.滚动数组:取模实现 2.位运算优先级最低 顾是if(!(a&b))而不是if(!a& ...
- luogu 2051 中国象棋
非常好的dp,锻炼思维 f[i][j][k] 前i行有j列放1,k列放2 #include<bits/stdc++.h> #define int long long #define rep ...
- BZOJ 4006 Luogu P3264 [JLOI2015]管道连接 (斯坦纳树、状压DP)
题目链接: (bzoj)https://www.lydsy.com/JudgeOnline/problem.php?id=4006 (luogu)https://www.luogu.org/probl ...
- luogu 2157 状压dp
f[i][j][k]分别代表1-i-1个人全部打完饭时i及其后7个人的状态为j时最后一个打饭的人为i+k的状态下所用的最小时间 当i已经打过饭时 即 j&1 那么 f [i] [j>&g ...
- luogu 2704 炮兵阵地 状压dp
状压的基础题吧 第一次看感觉难上天,后来嘛就.. 套路:先根据自身状态筛出可行状态,再根据地图等其他限制条件筛选适合的状态加入答案 f i,j,k 分别代表 行数,本行状态,上行状态,再累加答案即可 ...
随机推荐
- 探索 TypeScript 编程的利器:ts-morph 入门与实践
我们是袋鼠云数栈 UED 团队,致力于打造优秀的一站式数据中台产品.我们始终保持工匠精神,探索前端道路,为社区积累并传播经验价值. 本文作者:贝儿 背景 在开发 web IDE 中生成代码大纲的功能时 ...
- JDBC基础知识
常见连接数据库工具: 图形化工具:点击.拖拽就可以操作数据库,对用户友好,简单对数据操作,复杂数据库操作爱莫能助 JDBC(驱动程序):调用jar包接口 窗口(命令行):输入完整SQL语句对复杂数据库 ...
- MySQL中INSERT INTO ... ON DUPLICATE KEY UPDATE浅析
最近在做一个阅读次数的需求的时候,有这样一个场景,如果数据库中没有数据,就进行INSERT操作,有数据的话,阅读次数就+1.此处有两种实现方式,一种是想将数据查出来,在Java中进行处理,没有就INS ...
- uniapp多次触发跳转问题
问题描述:快速点击跳转页面后会闪退到登陆页面 解决方案:重新封装uniapp跳转api,加防抖锁,To.ts import { NavigateToOptions, RedirectToOptions ...
- 《Django 5 By Example》阅读笔记:p521-p542
<Django 5 By Example>学习第 18 天,p521-p542 总结,总计 22 页. 一.技术总结 1.django-parler django-parler 用于 mo ...
- COSBrowser 移动端——随时随地查看管理数据
外出身边没有电脑,需要查看管理数据怎么办? 出现紧急情况,需要快速停止某个 bucket 对外访问,怎么办? 个人用户仅作为网盘使用,需要方便轻量的管理工具,怎么办? 不用着急,COSBrowser ...
- [ARC107D] Number of Multisets题解
很显然的动态规划. 令 $f_{i,j}$ 为 $n=i$,$k=j$ 时满足题意的集合数. 依题意可得:一个集合可以只由另一个集合添加元素或将所有元素除二得到. 初始:$f_{0,0}=1$. 目标 ...
- 评 PowerShell
近来不得不接触 pwsh,发现竟然设计的这么漂亮. pwsh 的设计出发点:pwsh 的命令都是面向对象的,命令返回的是对象,命令传入的也是对象.对象在命令的管道间传递,从而组合出复杂任务. 这和 l ...
- 实践解决:IDEA2022版本创建Maven项目时没有出现src目录
问题:IDEA创建Maven项目时没有出现src目录 创建Maven项目 新版本的IDEA创建是选用的是Maven Archetype,选择这个也是和Maven一样的.按照这样流程创建完成之后的的架构 ...
- 如何在 Kubernetes Pod 和您的机器之间复制文件
在 Kubernetes Pod 中运行的容器是不需要手动交互的独立计算单元.有时您可能需要将文件复制到 Pod 的文件系统或从 Pod 的文件系统复制文件,这可能是因为您正在调试问题并希望存档存储在 ...