当前位置: 首页 > news >正文

【算法提高:动态规划】1.5 状态压缩DP TODO

文章目录

  • 状态压缩DP
  • 例题列表
    • 棋盘式
      • 1064. 小国王⭐🐂(好题!)
        • 做题套路总结
      • 327. 玉米田(好题!🐂 和1064. 小国王差不多的题目)
      • 292. 炮兵阵地(和上面两道题差不多,需要多考虑上上一行)
    • 集合
      • 524. 愤怒的小鸟🚹🚹🚹(TODO)
      • 529. 宝藏🚹🚹🚹🚹🚹(TODO)
  • 相关链接

状态压缩DP

状压 DP 是动态规划的一种,通过将状态压缩为整数来达到优化转移的目的。
在这里插入图片描述
更多介绍可见:相关链接 部分。

例题列表

棋盘式

1064. 小国王⭐🐂(好题!)

https://www.acwing.com/activity/content/problem/content/1292/

在这里插入图片描述

洛谷相同题目链接:P1896 [SCOI2005] 互不侵犯

每个国王会攻击周围一圈儿。

每一层只需要考虑上一层的状态就可以了。


dp数组定义:long[][][] dp = new long[N][K][M]; 第i行,已经放了j个国王,当前行的国王集合为a,此时的方案数。

枚举顺序见代码。

import java.io.BufferedInputStream;
import java.util.*;public class Main {final static int N = 12, M = 1 << 10, K = 110;      // 可以开大一点无所谓static int n, m;static List<Integer> state = new ArrayList<>();     // 里面存放的是在一行中没有冲突的集合static int[] cnt = new int[M];static List<Integer>[] head = new ArrayList[M];     // 里面存放的是每一种状态相邻的行可以放置哪些状态static long[][][] dp = new long[N][K][M];static {Arrays.setAll(head, e -> new ArrayList<>());}public static void main(String[] args) {Scanner sin = new Scanner(new BufferedInputStream(System.in));n = sin.nextInt();m = sin.nextInt();// 预先处理出所有可选的状态集合(即在一行内没有冲突的集合),以及这种状态的行中有几个国王for (int i = 0; i < 1 << n; ++i) {if (check(i)) {state.add(i);cnt[i] = count(i);}}// 预先处理每一行之后 相邻的行可以放置哪种状态集合for (int i = 0; i < state.size(); ++i) {for (int j = 0; j < state.size(); ++j) {int a = state.get(i), b = state.get(j);// 如果没有冲突// 没有列上一样的,也没有列上相邻的if ((a & b) == 0 && check(a | b)) {head[i].add(j);}}}// 第i行,已经放了j个国王,当前行的国王集合为adp[0][0][0] = 1;// 枚举每一行for (int i = 1; i <= n + 1; i++) {// 枚举已经选了m个国王(需要从0枚举到m)for (int j = 0; j <= m; ++j) {// 枚举每一种状态作为当前行(不管是不是合法的,无所谓,因为不合法的对应的head[a]里面是空的)for (int a = 0; a < state.size(); ++a) {// 枚举a后面可以跟着的每一种bfor (int b: head[a]) {int c = cnt[state.get(a)];// 如果当前已经选择的国王数量>=当前行的国王数量if (j >= c) {dp[i][j][a] += dp[i - 1][j - c][b];}}}}}System.out.println(dp[n + 1][m][0]);}// 检查一个状态集合是否在这一行内有冲突static boolean check(int state) {for (int i = 0; i < n; ++i) {// 如果连续两列都为1,表示有冲突if (((state >> i & 1) == 1 && (state >> i + 1 & 1) == 1)) return false;}return true;}// 计算这个状态集合中,摆放了几个国王static int count(int state) {int res = 0;for (int i = 0; i < n; ++i) res += state >> i & 1;return res;}
}

做题套路总结

最后来总结一下写法:

  1. 先预先处理出,所有在一行中没有冲突的列集合
  2. 然后对计算出对所有合理列集合 来说 没有冲突的列集合
  3. 最后 枚举行、当前行的列状态、上一行的列状态,计算状态转移

327. 玉米田(好题!🐂 和1064. 小国王差不多的题目)

https://www.acwing.com/problem/content/329/

在这里插入图片描述

跟上一题相比有一些变化:

  • 冲突的范围从周围一圈变成十字的形状
  • 部分格子是无法放置玉米的
  • 种植玉米的数量是没有限制的
import java.io.BufferedInputStream;
import java.util.*;public class Main {final static int N = 14;final static long MOD = (long)1e8;static int m, n;static int[] land = new int[N];         // 记录每一行中的哪些列是不能种植的static List<Integer> states = new ArrayList<>();        // 记录所有在一行中合法的状态static List<Integer>[] head = new ArrayList[1 << N];static {Arrays.setAll(head, e -> new ArrayList<>());}public static void main(String[] args) {Scanner sin = new Scanner(new BufferedInputStream(System.in));m = sin.nextInt();n = sin.nextInt();for (int i = 1; i <= m; ++i) {for (int j = 0; j < n; ++j) {int t = sin.nextInt();land[i] += (t ^ 1) << j;      // 0表示不育}}// 预先处理出在一行中合法的所有状态,加入states中for (int i = 0; i < 1 << n; ++i) {if (check(i)) states.add(i);}// 预先处理出哪两种行可以放在一起for (int i = 0; i < states.size(); ++i) {for (int j = 0; j < states.size(); ++j) {int a = states.get(i), b = states.get(j);// 只要这两行在列上没有重复,就可以放在一起if ((a & b) == 0) {head[i].add(j);}}}long[][] dp = new long[m + 2][states.size() + 1];dp[0][0] = 1;       // dp数组初始化// 枚举每一行for (int i = 1; i <= m + 1; ++i) {// 枚举该行的状态for (int j = 0; j < states.size(); ++j) {if ((states.get(j) & land[i]) == 0) {// 枚举可以从这种行转移过来的行for (int k: head[j]) {dp[i][j] = (dp[i][j] + dp[i - 1][k]) % MOD;}}}}System.out.println(dp[m + 1][0]);}static boolean check(int state) {for (int i = 0; i < n - 1; ++i) {// 检查是否有连续两位都是1的情况if ((state >> i & 1) == 1 && ((state >> i + 1 & 1) == 1)) return false;}return true;}
}

Q:为什么 dp[][] 数组初始化时只 设置 dp[0][0] = 1,而不把 所有 dp[0][j] = 1?
A:dp[0][0] = 1表示在还没有种植任何玉米的状态下(也就是前0行),这种情况只有1种。而dp[0][j] (j != 0)的含义是,在还没有种植任何玉米的状态下,最后一行(也就是不存在的这一行)的种植状态是states[j]的种植方式数量,这显然是不可能的,所以dp[0][j] (j != 0)都应该为0。

292. 炮兵阵地(和上面两道题差不多,需要多考虑上上一行)

https://www.acwing.com/problem/content/294/

在这里插入图片描述

跟上面两道题目相比,多考虑上上一行就好了。
dp 递推的过程也 多写一层循环。

import java.io.BufferedInputStream;
import java.util.*;public class Main {final static int N = 105, M = 11;static int n, m;static int[] land = new int[N], cnt = new int[1 << M];         // 记录每一行,不能放置炮兵的列集合static List<Integer> states = new ArrayList<>();    // 记录所有在一行中合理的列集合static List<Integer>[] head = new ArrayList[1 << M];static {Arrays.setAll(head, e -> new ArrayList<>());}public static void main(String[] args) {Scanner sin = new Scanner(new BufferedInputStream(System.in));n = sin.nextInt();m = sin.nextInt();// 记录每一行不能被放置的列集合for (int i = 1; i <= n; ++i) {String s = sin.next();for (int j = 0; j < m; ++j) {land[i] += (s.charAt(j) == 'H'? 1: 0) << j;}}// 计算出所有在一行中合理的列集合for (int j = 0; j < 1 << m; ++j) {if (check(j)) {states.add(j);cnt[j] = count(j);}}// 计算出各个集合可以和哪些集合相邻int l = states.size();for (int i = 0; i < l; ++i) {for (int j = 0; j < l; ++j) {if ((states.get(i) & states.get(j)) == 0) {head[i].add(j);}}}int[][][] dp = new int[n + 1][l][l];// 枚举每一行for (int r = 1; r <= n; ++r) {// 枚举当前的每个集合for (int i = 0; i < l; ++i) {if ((states.get(i) & land[r]) == 0) {// 枚举上一个集合for (int j: head[i]) {// 枚举上上个集合for (int k: head[j]) {if ((states.get(i) & states.get(k)) == 0) {dp[r][j][i] = Math.max(dp[r - 1][k][j] + cnt[states.get(i)], dp[r][j][i]);}}}}}}int ans = 0;for (int i = 0; i < l; ++i) {for (int j = 0; j < l; ++j) {ans = Math.max(ans, dp[n][i][j]);}}System.out.println(ans);}private static boolean check(int state) {for (int i = 0; i < m; ++i) {       // 这里最好写成 i < m,写成 i < m - 2 时答案就不对了// 邻近两个范围内不能有炮兵if ((state >> i & 1) == 1 && ((state >> i + 1 & 1) == 1 || (state >> i + 2 & 1) == 1)) return false;}return true;}// 计算这种集合中有多少个炮兵static int count(int state) {int res = 0;for (int i = 0; i < m; ++i) res += state >> i & 1;return res;}
}

集合

524. 愤怒的小鸟🚹🚹🚹(TODO)

https://www.acwing.com/problem/content/526/
在这里插入图片描述
在这里插入图片描述
数据范围
在这里插入图片描述

在这里插入代码片

529. 宝藏🚹🚹🚹🚹🚹(TODO)

https://www.acwing.com/problem/content/531/
在这里插入图片描述

在这里插入代码片

相关链接

从集合论到位运算——常见位运算技巧及相关习题 & 状态压缩DP
【力扣周赛】第 355 场周赛(构造&二分答案&异或前缀 状态压缩⭐)
【算法基础:动态规划】5.4 状态压缩DP

相关文章:

【算法提高:动态规划】1.5 状态压缩DP TODO

文章目录 状态压缩DP例题列表棋盘式1064. 小国王⭐&#x1f402;&#xff08;好题&#xff01;&#xff09;做题套路总结 327. 玉米田&#xff08;好题&#xff01;&#x1f402; 和1064. 小国王差不多的题目&#xff09;292. 炮兵阵地&#xff08;和上面两道题差不多&#xff…...

建网站一般使用Windows还是liunx好?

建网站一般使用Windows还是liunx好&#xff1f; 1&#xff1b;服务器配置比较低时&#xff0c;最好使用linux系统。 对于一个电脑新手&#xff0c;刚开始做网站时&#xff0c;都会选择入门级的服务器&#xff0c;我刚开始做网站时&#xff0c;就是这样的。我购买了一台入门级服…...

NodeJs后端项目使用docker打包部署

docker安装看之前的文章 默认已经安装好docker并且配置没有问题 拉取项目 https://gitee.com/coder-msc/docker-node 本地跑一个看看 pnpm install pnpm start 本地访问 http://localhost:1301/getname?name%E5%93%88%E5%88%A9%E6%B3%A2%E7%89%B9项目整个上传服务器 查看…...

ARM单片机中断处理过程解析

前言 中断&#xff0c;在单片机开发中再常见不过了。当然对于中断的原理和执行流程都了然于胸&#xff0c;那么对于ARM单片机中断的具体处理行为&#xff0c;你真的搞清楚了吗&#xff1f; 今天来简单聊一聊&#xff0c;ARM单片机中断处理过程中的具体行为是什么样的&#xf…...

关于SEDEX会员与平台的相关问题汇总

【关于SEDEX会员与平台的相关问题汇总】 01.会员资格有效期是多久&#xff1f; Sedex会员资格有效期为12个月&#xff0c;您也可以选择更长期的会员资格。您支付会员年费时&#xff0c;在“订阅信息”框下的“延长订阅期限”中输入年数&#xff0c;即可获得更长的会员资格时效。…...

解读Spring-context的property-placeholder

在spring中&#xff0c;如果要给程序定义一些参数&#xff0c;可以放在application.properties中&#xff0c;通过<context:property-placeholder>加载这个属性文件&#xff0c;然后就可以通过value给我们的变量自动赋值&#xff0c;如果你们的程序可能运行在多个环境中&…...

【Rust】枚举类型创建单链表以及常见的链表操作方法

目录 单链表 用枚举表达链表 枚举enum Box容器 创建节点 1. 创建并打印 2. match 匹配 3. 节点初始化 4.节点嵌套 追加节点 1. 尾插法 2. 链表追加方法 3. 头插法 4. 改写成单链表方法 遍历链表 1. 递归法 2. 递推法 3. 改写成单链表方法 自定义Display tr…...

Excel 两列数据中相同的数据进行同行显示

一、要求 假设您有两个列&#xff0c;分别是A列和B列&#xff0c;需要在C列中找出A列对应的B列的值。 二、方案 方法1&#xff1a;寻常思路 凸显重复项对A列单独进行筛选–按颜色进行排序&#xff0c;然后升序对B列重复上述操作即可 方法2&#xff1a;两个公式 VLOOKUP 纵向查找…...

Windows本地安装配置Qcadoo MES系统

简介 Qcadoo MES是一款功能强大且灵活的开源MES&#xff08;制造执行系统&#xff09;&#xff0c;旨在为制造业务提供全面的管理和监控解决方案。本篇博客将教您如何在Windows操作系统上安装和配置Qcadoo MES系统&#xff0c;以便您能够轻松管理和监控制造过程。 环境要求 …...

涛思数据与拾贝云达成战略合作,携手赋能工业数字化转型

2023 年 7 月 27 日&#xff0c;北京涛思数据科技有限公司&#xff08;以下简称“涛思数据”&#xff09;与广州拾贝云科技有限公司&#xff08;以下简称“拾贝云”&#xff09;于广州签署战略合作协议。双方围绕电力行业的需求与痛点展开积极讨论&#xff0c;就如何量身打造最…...

nginx 配置多域名多站点 Ubuntu

nginx 配置多域名多站点 Ubuntu 一、安装 nginx apt install nginx二、配置文件说明 nginx 的配置文件在 /etc/nginx 目录下&#xff0c;它的默认内容是这样的 root2bd0:/etc/nginx# ll total 72 drwxr-xr-x 8 root root 4096 Jul 31 15:21 ./ drwxr-xr-x 104 root root …...

Docker实践:使用Docker搭建个人开发环境(极简版)

文章目录 说明教程1. 编写 Dockerfile2. 编写 docker-compose.yml3. 使用容器创建容器启动容器进入容器命令行VSCode 4. 关闭容器5. 备份容器导出导入 6. 重置容器 相关资料文章合集详细了解本文在个人电脑上安装 Docker容器使用 NVIDIA 显卡托管镜像运行GUI程序 说明 本文是在…...

SQL从三个表中根据时间分别查询并汇总数量一行展示

需求&#xff1a;如果您要从三个表中根据时间分别查询并汇总数量&#xff0c;然后将结果以时间和数量一行展示&#xff0c;可以使用子查询和条件聚合。 入库主表 入库明细表 出库主表 出库明细表 退货主表 退货明细表 SQL代码 SELECT time,sum(a.inQty) as inQty,sum(a.outQty…...

同样是跨端框架,React会不会被VUE取代?

看到知乎上有比较多的类似问题&#xff0c;正好这两个框架在以往的一些项目中都有实践过&#xff0c;就借着本篇文章说说我个人的看法。 先摆个结论&#xff1a;不会&#xff0c;毕竟各有千秋&#xff0c;除非跨端框架有被更好的概念所替代&#xff0c;又或者App已经彻底过气了…...

Excel·VBA定量装箱、凑数值金额、组合求和问题

如图&#xff1a;对图中A-C列数据&#xff0c;根据C列数量按照一定的取值范围&#xff0c;组成一个分组装箱&#xff0c;要求如下&#xff1a; 1&#xff0c;每箱数量最好凑足50&#xff0c;否则为47-56之间&#xff1b; 2&#xff0c;图中每行数据不得拆分&#xff1b; 3&…...

通过Jmeter压测存储过程

目录 一、存储过程准备&#xff1a; 二、测试工具准备&#xff1a; 三、工具配置及执行&#xff1a; 1、配置JDBC Connection Configuration&#xff1a; 2、配置吞吐量控制器&#xff08;可跳过&#xff09;&#xff1a; 3、配置JDBC Request&#xff1a; 对于存储过程…...

Spring笔记之Spring对IoC的实现

文章目录 IoC控制反转依赖注入set注入注入外部Bean注入内部Bean注入简单类型通过注入方式实现javax.sql.DateSource接口测试简单类型 级联属性赋值&#xff08;了解&#xff09;注入数组注入List集合注入Set集合注入Map集合注入Properties注入null和空字符串不给属性赋值使用 注…...

【eNSP】Telnet远程登录

Telnet远程登录 eNSP软件TelnetTelnet远程登录-路由连接关闭防火墙eNSP根据图1画图路线配置路由端口IP配置路由R1改名配置接口IP 配置路由R2 配置R2的远程登录设置登录用户授权级别退出登录超时时间 Telnet测试 eNSP软件 eNSP(Enterprise Network Simulation Platform)是一款由…...

SOP/详解*和**/python数据结构(iter,list,tuple,dict)/ 解包

一、错误解决合集 1. > combined_seq.named_children() 2. isinstance 2th parameter : must be a type or tuple of types > 改为tuple&#xff0c;不要用列表。改为 LLLayer (nn.Conv2d,nn.Linear) 3. File “test.py”, line 90, in calculate_fin_fout print(“hi”…...

使用webdriver-manager解决浏览器与驱动不匹配所带来自动化无法执行的问题

1、前言 在我们使用 Selenium 进行 UI 自动化测试时&#xff0c;常常会因为浏览器驱动与浏览器版本不匹配&#xff0c;而导致自动化测试无法执行&#xff0c;需要手动去下载对应的驱动版本&#xff0c;并替换原有的驱动&#xff0c;可能还会遇到跨操作系统进行测试的时候&…...

Lombok 的 @Data 注解失效,未生成 getter/setter 方法引发的HTTP 406 错误

HTTP 状态码 406 (Not Acceptable) 和 500 (Internal Server Error) 是两类完全不同的错误&#xff0c;它们的含义、原因和解决方法都有显著区别。以下是详细对比&#xff1a; 1. HTTP 406 (Not Acceptable) 含义&#xff1a; 客户端请求的内容类型与服务器支持的内容类型不匹…...

日语学习-日语知识点小记-构建基础-JLPT-N4阶段(33):にする

日语学习-日语知识点小记-构建基础-JLPT-N4阶段(33):にする 1、前言(1)情况说明(2)工程师的信仰2、知识点(1) にする1,接续:名词+にする2,接续:疑问词+にする3,(A)は(B)にする。(2)復習:(1)复习句子(2)ために & ように(3)そう(4)にする3、…...

Oracle查询表空间大小

1 查询数据库中所有的表空间以及表空间所占空间的大小 SELECTtablespace_name,sum( bytes ) / 1024 / 1024 FROMdba_data_files GROUP BYtablespace_name; 2 Oracle查询表空间大小及每个表所占空间的大小 SELECTtablespace_name,file_id,file_name,round( bytes / ( 1024 …...

IGP(Interior Gateway Protocol,内部网关协议)

IGP&#xff08;Interior Gateway Protocol&#xff0c;内部网关协议&#xff09; 是一种用于在一个自治系统&#xff08;AS&#xff09;内部传递路由信息的路由协议&#xff0c;主要用于在一个组织或机构的内部网络中决定数据包的最佳路径。与用于自治系统之间通信的 EGP&…...

STM32+rt-thread判断是否联网

一、根据NETDEV_FLAG_INTERNET_UP位判断 static bool is_conncected(void) {struct netdev *dev RT_NULL;dev netdev_get_first_by_flags(NETDEV_FLAG_INTERNET_UP);if (dev RT_NULL){printf("wait netdev internet up...");return false;}else{printf("loc…...

鸿蒙中用HarmonyOS SDK应用服务 HarmonyOS5开发一个医院挂号小程序

一、开发准备 ​​环境搭建​​&#xff1a; 安装DevEco Studio 3.0或更高版本配置HarmonyOS SDK申请开发者账号 ​​项目创建​​&#xff1a; File > New > Create Project > Application (选择"Empty Ability") 二、核心功能实现 1. 医院科室展示 /…...

Vue2 第一节_Vue2上手_插值表达式{{}}_访问数据和修改数据_Vue开发者工具

文章目录 1.Vue2上手-如何创建一个Vue实例,进行初始化渲染2. 插值表达式{{}}3. 访问数据和修改数据4. vue响应式5. Vue开发者工具--方便调试 1.Vue2上手-如何创建一个Vue实例,进行初始化渲染 准备容器引包创建Vue实例 new Vue()指定配置项 ->渲染数据 准备一个容器,例如: …...

ETLCloud可能遇到的问题有哪些?常见坑位解析

数据集成平台ETLCloud&#xff0c;主要用于支持数据的抽取&#xff08;Extract&#xff09;、转换&#xff08;Transform&#xff09;和加载&#xff08;Load&#xff09;过程。提供了一个简洁直观的界面&#xff0c;以便用户可以在不同的数据源之间轻松地进行数据迁移和转换。…...

从零实现STL哈希容器:unordered_map/unordered_set封装详解

本篇文章是对C学习的STL哈希容器自主实现部分的学习分享 希望也能为你带来些帮助~ 那咱们废话不多说&#xff0c;直接开始吧&#xff01; 一、源码结构分析 1. SGISTL30实现剖析 // hash_set核心结构 template <class Value, class HashFcn, ...> class hash_set {ty…...

第 86 场周赛:矩阵中的幻方、钥匙和房间、将数组拆分成斐波那契序列、猜猜这个单词

Q1、[中等] 矩阵中的幻方 1、题目描述 3 x 3 的幻方是一个填充有 从 1 到 9 的不同数字的 3 x 3 矩阵&#xff0c;其中每行&#xff0c;每列以及两条对角线上的各数之和都相等。 给定一个由整数组成的row x col 的 grid&#xff0c;其中有多少个 3 3 的 “幻方” 子矩阵&am…...