【算法每日一练]-动态规划(保姆级教程 篇17 状态压缩)#POJ1185:炮兵阵地 #互不侵犯

目录

今日知识点:

把状态压缩成j,dp每行i的布置状态,从i-1和i-2行进行不断转移

把状态压缩成j,dp每行i的布置状态,从i-1行进行状态匹配,然后枚举国王数转移

 POJ1185:炮兵阵地

思路:

题目:互不侵犯

思路:


        

        

 POJ1185:炮兵阵地

在N*M(N<100,M<10)的地图上布置炮兵,H格子为山地不能布置,P格子为平原可以布置。炮兵的攻击范围是沿横向左右各两格,沿纵向上下个两格子
炮兵之间不能误伤。问在整个地图中最多能拜访多少个炮兵?
5 4
PHPP
PPHH
PPPP
PHPP
PHHP

        

思路:

还是那么句话,每个格子都有2种状态,如果搜索就要把所有结果都跑出来,所以只能使用状压dp 。      

而且方程的转移和上一行的状态有关,但是状态又太多了,故要状态压缩。

首先要对行进行状态压缩(对列的话太大了,枚举2^100还不如不压缩呢),我们每次确定行的状态都需要考虑:
1.横向方案    2.横向方案是否和地图匹配     3.是否和i-1行i-2行冲突
设置dp[i][j][k]表示第i行为第j状态,第i-1行为第k状态时 对应的前i行放置的最大炮兵数。
转移方程:dp[i][j][k]=max(dp[i][j][k],dp[i-1][k][t]+num[j]);(num是对应状态的炮兵个数)

(j是第i行的方案,k是第i-1行的方案,t是i-2行的方案)
存每行的可能状态:左右相邻1个间隔和2个间隔都不能炮兵(就是可能的横向方案)
存图:(1,1)开始存。0表示平原,1表示山地,那么在放置的时候不能出现同1(在山地放炮兵),所以x&y=0是合法的(保证合法的是0就行了)
是否冲突:第i行和第i-1行,第i-2行 不能出现有一列同1(两行都放炮兵),所以x&y=0是合法的

        
【注意】:外面每行i循环一次,其次里面是第i行的每个状态j循环一次(找到合适的j),然后是第i-1行的每个状态k循环一次(供第i行找到合适的k),
接着是第i-2行的每个状态t循环一次(供第i-1行找到合适的t)

#include <bits/stdc++.h>
using namespace std;
int n,m,top;
char mp[110][20];
int num[70];//num存放状态对应的炮兵个数
int ok[70],cur[70];//ok表示横向可能的方案,cur是我们存的地图行
int dp[110][70][70];bool check(int x){if(x&(x<<1))return 0;//相邻1间隔是否合法if(x&(x<<2))return 0;//相邻2间隔是否合法return 1;
}void init(){//统计所有的可能合法状态,最多60种top=0;for(int i=0;i<(1<<m);i++){//不能取等,不能取等!!!if(check(i))ok[top++]=i;}
}int count(int x){//统计x二进制中1的个数int cnt=0;while(x){if(x&1)cnt++;x=x>>1;}
//	while(x){//这个更快
//		cnt++;
//		x&=(x-1);
//	}	return cnt;
}int solve(){int ans=0;memset(dp,-1,sizeof(dp));for(int j=0;j<top;j++){//初始化第一行的状态num[j]=count(ok[j]);//记录每个正确状态的炮兵个数if(!(ok[j]&cur[1])){//和地图匹配dp[1][j][0]=num[j];//第一行状态为j,上一行状态为0(知道为啥从(1,1)开始初始化了把)ans=max(ans,dp[1][j][0]);}}for(int i=2;i<=n;i++){//处理每一行for(int j=0;j<top;j++){//遍历第i行的可能方案if(ok[j]&cur[i])continue;//是否和地图匹配for(int k=0;k<top;k++){//遍历第i-1行的可能方案if(ok[j]&ok[k])continue;//此行和上一行是否匹配(不用再判断和地图是否匹配,不匹配dp是-1,不影响的)for(int t=0;t<top;t++){//遍历上二行可能方案if(ok[j]&ok[t])continue;//此行和上二行是否匹配dp[i][j][k]=max(dp[i][j][k],dp[i-1][k][t]+num[j]);}if(i==n)ans=max(ans,dp[i][j][k]);//不要放在外面套3个for取max}}}return ans;
}
int main(){while(cin>>n>>m){init();for(int i=1;i<=n;i++){scanf("%s",mp[i]+1);//加1是为了从1下标开始存}for(int i=1;i<=n;i++){cur[i]=0;for(int j=1;j<=m;j++){if(mp[i][j]=='H')//同样的,不能放的地方存1cur[i]+=(1<<(m-j));}}cout<<solve();}
}

        

        

题目:互不侵犯

思路:

可以看到和炮兵阵地题非常像,跑不了是状压dp。

还是那句话,每个方格都有两种状态,搜索的话必然是要全部搜索一下,放弃吧(况且,不谈超时,你真的把本道题的dfs其实也够呛的)。

设置dp[i][j][k]表示第i行为j状态时已经放了k个国王对应的方案数。

转移方程:dp[i][j][k]=dp[i-1][i-1行所有的合法状态][k-对应状态的国王数];

然后就是对状态的处理:

行内状态:我们要保证相与出0合法,非0不合法。那么对s行,

有:(((s<<1)&s==0)&&((s>>1)&s)==0)算合法,

等价于这个写法:(((s<<1)|(s>>1))&s)==0。   千万别少写红色括号!!!
行间状态:((s2&s1==0)&&((s2>>1)&s1==0)&&((s2<<1)&s1)==0)才算合法,

等价于:(((s2|(s2>>1)|(s2<<1))&s1)==0。

循环方式:首先是每行,然后选择该行状态,然后是上行状态,判断两行状态是否匹配,如果匹配就枚举国王数,最后转移方程!

#include <bits/stdc++.h>
using namespace std;
int num,n,k;//ok存正确的行状态,cnt存状态对应的国王数
long long dp[10][100][2000],cnt[2000],ok[2000];
int main(){cin>>n>>k;for(int s=0;s<(1<<n);s++){//遍历出所有的正确状态iint tot=0,tmp=s;while(tmp){if(tmp&1)tot++;tmp>>=1;}cnt[s]=tot;//存每个状态的国王数if((((s<<1)|(s>>1))&s)==0) ok[++num]=s;}dp[0][0][0]=1;for(int i=1;i<=n;i++){//从第一行开始转移for(int ss1=1;ss1<=num;ss1++){int s1=ok[ss1];//选择第一行的状态for(int ss2=1;ss2<=num;ss2++){int s2=ok[ss2];//选择上一行的状态if(((s2|(s2<<1)|(s2>>1))&s1)==0){//如果这两行状态合法for(int j=0;j<=k;j++){//对国王数进行枚举转移if(j-cnt[s1]>=0)dp[i][j][s1]+=dp[i-1][j-cnt[s1]][s2];}}}}}long long ans=0;for(int i=1;i<=num;i++)ans+=dp[n][k][ok[i]];cout<<ans;
}

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/767925.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

代码随想录算法训练营第二十八天|● 93.复原IP地址 ● 78.子集 ● 90.子集II (JS写法)

93 复原IP地址 题目链接/文章讲解&#xff1a;https://programmercarl.com/0093.%E5%A4%8D%E5%8E%9FIP%E5%9C%B0%E5%9D%80.html 视频讲解&#xff1a;https://www.bilibili.com/video/BV1XP4y1U73i/ 思路&#xff1a; /*** param {string} s* return {string[]}*/ var resto…

微信商家转账到零钱:实用指南,涵盖开通、使用与常见问题

商家转账到零钱是什么&#xff1f; 商家转账到零钱功能整合了企业付款到零钱和批量转账到零钱&#xff0c;支持批量对外转账&#xff0c;操作便捷。如果你的应用场景是单付款&#xff0c;体验感和企业付款到零钱基本没差别。 商家转账到零钱的使用场景有哪些&#xff1f; 这…

基于YOLOv8深度学习的橙子病害智能诊断与防治系统【python源码+Pyqt5界面+数据集+训练代码】深度学习实战、目标分类

《博主简介》 小伙伴们好&#xff0c;我是阿旭。专注于人工智能、AIGC、python、计算机视觉相关分享研究。 ✌更多学习资源&#xff0c;可关注公-仲-hao:【阿旭算法与机器学习】&#xff0c;共同学习交流~ &#x1f44d;感谢小伙伴们点赞、关注&#xff01; 《------往期经典推…

【动态规划】Leetcode 746. 使用最小花费爬楼梯

【动态规划】Leetcode 746. 使用最小花费爬楼梯 解法 ---------------&#x1f388;&#x1f388;题目链接&#x1f388;&#x1f388;------------------- 解法 &#x1f612;: 我的代码实现> 动规五部曲 ✒️确定dp数组以及下标的含义 dp[i] 表示跳跃到第 i 层&#x…

「Swift」AttributedString常见使用方法

前言&#xff1a;AttributedString是Apple推出的可以实现单个字符或字符范围带相应属性的字符串。属性提供了一些文本特性&#xff0c;可以让文本展示的样式更加丰富。在日常开发过程中&#xff0c;我通常用于同一个Label中包含不同的字体大小或字体颜色的样式编写中。 使用举…

11 Games101 - 笔记 - 几何(曲线与曲面)

11 几何&#xff08;曲线与曲面&#xff09; 贝塞尔曲线 定义 贝塞尔曲线&#xff1a;由控制点和线段组成的曲线&#xff0c;控制点是可拖动的支点。 如图&#xff0c;蓝色为贝塞尔曲线&#xff0c;p1, p2, p3为控制点&#xff0c;曲线和初始与终止端点相切&#xff0c;并且…

【原理图PCB专题】Cadence 17.4版本导出excel版本坐标文件

坐标文件记录了板卡上每个元件的坐标是生产的基础资料,在PCBA生产时,需要提坐标文件并且务必保证 准确无误。 Cadence导出坐标文件大部分网上的都是txt文件,其格式如下。导出的文件存在没有对应的Title,格式打开混乱等问题。 那么Cadence 17.4版本如何导出有标题、…

分布式系统的基本特性

一般&#xff0c;分布式系统需要支持以下特性&#xff1a; 资源共享 开放性 并发性 可伸缩性 容错性 透明性 下面分别讨论。 容易理解的 资源共享 一旦授权&#xff0c;可以访问环境中的任何资源。 资源&#xff1a;包括硬件(e.g. printer, scanner, camera)、软件&a…

对于组件通信的深刻理解

父组件传递数据给子组件 props传递数据 父组件在子组件的标签上写自定义的属性,属性值是自己的变量,当渲染到子组件时,执行props会找自定义属性,内存了变量的内存,可访问到,写props,会生成vue实例的时候,将props的变量赋给,值找变量内存存入变量.插值语句等可访问.父组件会变…

python综合实战案例-数据分析

Python是进行数据分析的好工具&#xff0c;今天就是借助一个案例给大家进行数据分析讲解。 本例设计一个log.txt⽂件&#xff0c;该文件记录了某个项⽬中某个 api 的调⽤情况&#xff0c;采样时间为每分钟⼀次&#xff0c;包括调⽤次数、响应时间等信息&#xff0c;⼤约18万条数…

如何在 Django 中使用 pyecharts

为项目新建一个目录&#xff0c;将其命名为django_pyecharts_demo, 在终端中切换到这个目录&#xff0c;并创建一个虚拟环境。 python -m venv django_pyecharts激活虚拟环境 django_pyecharts\Scripts\activate要停止使用虚拟环境&#xff0c;可执行命令 deactivate创建并激…

【论文精读】MAE:Masked Autoencoders Are Scalable Vision Learners 带掩码的自动编码器是可扩展的视觉学习器

系列文章目录 【论文精读】Transformer&#xff1a;Attention Is All You Need 【论文精读】BERT&#xff1a;Pre-training of Deep Bidirectional Transformers for Language Understanding 【论文精读】VIT&#xff1a;vision transformer论文 文章目录 系列文章目录一、前言…

24. UE5 RPG制作属性面板(二)

在上一篇中&#xff0c;我们创建属性面板的大部分样式&#xff0c;这一篇里面接着制作。 在这一篇里我们需要有以下几个方面&#xff1a; 在界面增加一个属性按钮。属性按钮增加事件&#xff0c;点击时可以打开属性面板&#xff0c;属性面板打开时无法再次点击按钮。点击属性面…

手撕算法-无重复字符的最长子串

描述 分析 滑动窗口&#xff0c;记录窗口中的所有出现的字符&#xff0c;然后窗口左边界固定&#xff0c;右边界右滑&#xff0c;如果&#xff0c;窗口中不存在新的字符&#xff0c;则右滑成功&#xff0c;否则左边界右滑&#xff0c;直到窗口中不存在右边界的值。 描述感觉不…

Centos7 防火墙iptables?

Centos7 防火墙iptables&#xff1f; 文章目录 Centos7 防火墙iptables&#xff1f;1. 介绍2. firewalld 和 iptables区别3. 区域管理概念区域管理有如下几种不同的初始化区域&#xff1a; 4.iptables的配置1.简述2.基本原理3.iptables传输数据包的过程4. iptables规则表和链5.…

结构体类型详细讲解(附带枚举,联合)

前言&#xff1a; 如果你还对结构体不是很了解&#xff0c;那么本篇文章将会从 为什么存在结构体&#xff0c;结构体的优点&#xff0c;结构体的定义&#xff0c;结构体的使用与结构体的大小依次介绍&#xff0c;同样会附带枚举与联合体 目录 为什么存在结构体&#xff1a; 结构…

【Linux 驱动基础】IMX6ULL LED基础驱动

本机使用的是正点原子的IMX6ULL开发板 # 前置知识 IMX6ULL GPIO控制框图&#xff1a; GPIO控制代码大概分为几个流程&#xff1a;开启时钟、设置IO复用、设置IO属性、配置IO方向、设置IO输出电平&#xff0c;下面以IMX6ULL为例&#xff0c; 1. 开启时钟 参考资料&#xff1a…

深入理解 Docker 镜像

1. Docker 镜像的底层原理 1.1 分层的镜像 以我们的pull 命令为例&#xff0c;在下载的过程中我们可以看到docker的镜像好像是一层一层的在下载。 1.2 UnionFS(联合文件系统) 联合文件系统是一种分层、轻量级并且高性能的文件系统&#xff0c;它支持对文件系统的修改作为一次…

MPI4.1文档翻译(持续更新)

本博客参考官方文档进行介绍&#xff0c;全网仅此一家进行中文翻译&#xff0c;走过路过不要错过。 官方网址&#xff1a;https://www.mpi-forum.org/ 参考文档&#xff1a;https://www.mpi-forum.org/docs/mpi-4.1/mpi41-report.pdf 引用官方4.1文档方法&#xff1a; manu…

linux下使用迅雷的完美办法(网络版免费),其他下载工具

迅雷有自家服务器的支持&#xff0c;因此&#xff0c;其他下载器&#xff0c;可能难以匹敌 &#xff1f; linux下使用迅雷的完美办法&#xff08;免费&#xff09; https://blog.csdn.net/lqrensn/article/details/8853949 网络版 Linux下安装并使用迅雷 https://www.lxlin…