【算法】状态压缩DP

news/2024/11/15 0:33:52/文章来源:https://www.cnblogs.com/DLShark/p/18537418

基本内容

  • 入门例子 USACO06NOV] Corn Fields G - 洛谷 | 计算机科学教育新生态

题目简述:在一个\(N\times M\)的玉米田中种玉米,有一些坏掉的土地是不能种玉米的,另外相邻的两个田也不可以种,一共有多少种种植方案(荒地也算一种),如图所示,由于相邻的土地不能种植,此时一号土地已经不能种植

image

  • 暴力解法

​ 每一行的玉米田有\(2^M\)种种植状态,再加上每一行的状态搜索,共有\(2^{M+N}\)种状态,并且还需要判断该状态是否合法,时间复杂度非常高。

  • 只考虑一行玉米田状态

​ 由于每一行的状态都是\(2^M\)种,并且可以种植的满足条件一致: ① 坏田不能种植 ② 相邻的田不能种植

​ 首先只考虑相邻田不能种植的情况 ① 坏田不能种植 ,可以发现,若只考虑玉米田只有一行的情况下,每一行的满足状态都是一样的,因此,可以先对不满足的种植状态去除。当我们用 0,1 表示田地的种植状态时,M列的玉米田可表示一个M位二进制数。例如该状态可以表示为二进制数 101,即为5,通过一个十进制数来表示当前行玉米田的状态。在遍历状态时可以减少运算效率。

image

def check(x):for i in range(m): if (x >> i & 1) & (x >> (i + 1) & 1): #(位运算,若为1则表示有相邻的玉米田种植,不满足状态)return Falsereturn True
  • 考虑多行玉米田状态

​ 由于受到相邻田不能种植的条件影响,当第\(i-1\)\(M\)列的玉米田被种植时,第\(i\)\(M\)列就无法被种植,可以发现每一行的状态只受到上一行状态的影响,并且\(i-1\)行的状态确定时,第\(i\)行的状态数目也确定了,这也就是状态压缩DP的关键,将多行的状态变换用一个状态转移的方式表示出来。如图所示,左图第一行的种植状态是100,第二行可以满足的数目是3;由于右图第二行的种植状态与其一致,因此右图第三行的满足数目也是3,

image

​ 将第\(i-1\)行的状态设为\(a\),第\(i\)的状态设为\(b\),满足状态的代码如下所示:

# states 存储的是玉米田只有一行时的满足状态
# heads 一个字典,存储某一个状态可以转化为下一行的全部状态
for i in range(len(states)):for j in range(len(states)):a, b = states[i], states[j]if (a & b) == 0: # 表示上下没有相邻的1,若有,则会出现某一位二进制位为1,不为0heads[a].append(b) # 将b的状态加入到a的满足状态中
  • 坏田不能种植

​ 当分析完相邻的田不能种植条件后,还需要分析坏田不能种植的情况,相对于上面的状态转移,这种情况较好分析,只需要满足当前行玉米田的坏田状态与当前状态是否有同时为1的列即可,若有则当前状态不满足,若无则满足,该条件判断与判断相邻行是否同时种植一致

  • 解题代码
M, N = map(int, input().split())
data = [list(map(int, input().split())) for _ in range(M)]
g = [(~int("".join(map(str, row)), 2)) & ((1 << N) - 1) for row in data]  # 取反
mod = 100000000 
g.append(1 << N)def check(x):for i in range(N): if (x >> i & 1) & (x >> (i + 1) & 1):  # 位运算,若有相邻的玉米田种植,不满足状态return Falsereturn True
heads = {}
states = []
for i in range(1 << N):if check(i):states.append(i)heads[i] = []for i in range(len(states)):for j in range(len(states)):a, b = states[i], states[j]if (a & b) == 0: # 表示上下没有相邻的1,若有,则会出现某一位二进制位为1,不为0heads[a].append(b) # 将b的状态加入到a的满足状态中
f = [[0 for _ in range(1 << N)]for _ in range(M + 2)]
f[0][0] = 1
for i in range(1, M+2): #本来是遍历到M即可,但遍历到M+1时可以在最后输出的时候直接取0状态即为前M层的最大数量for a in states:if g[i-1] & a:continuefor b in heads[a]:f[i][a] = (f[i][a] + f[i-1][b]) % mod
print(f[M+1][0]) 

题目

  1. N皇后问题

题目与玉米田的思路基本一致,多了一个判断问题,即对角的国王也会相互攻击,为了加入此情况,在状态转移的判断条件上需要加入对角判断的处理

image

  • 状态满足代码修改
for i in range(len(states)):for j in range(len(states)):a, b = states[i], states[j]if (a & b) == 0 and check(a | b):# 只需在这部分上加入check(a | b),因为对角没有互相攻击即为交集没有相邻的两个皇后heads[a].append(b) 

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

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

相关文章

ExtentReport报告配置

添加依赖<dependency><groupId>org.testng</groupId><artifactId>testng</artifactId><version>6.10</version></dependency><dependency><groupId>com.relevantcodes</groupId><artifactId>extentre…

教资成绩出来了,果然没有全过

教师资格证考试成绩出来了,有一科没有过, 出乎我的意料,我以为全军覆没了。马上38了,自己也算大龄程序员了。所以今年开始就一直在考虑退路了。 思来想去,关注到了信奥这个赛道。4月份公众号开始发信奥相关的文章,也在教资报名的时候去报了个名,想着有个教资证书,也能给…

Toyota Programming Contest 2024#11(AtCoder Beginner Contest 379)题解

Toyota Programming Contest 2024#11(AtCoder Beginner Contest 379)题解 总体情况A - Cyclic 题意 给你一个三位整数 \(N\) ,其中每个数字都是介于 \(1\) 和 \(9\) 之间的整数。 设 \(a\) , \(b\) , \(c\) 分别是 \(N\) 的百位、十位和个位数。打印一个按此顺序排列 \(b\) …

了解python

Python前世今生 Python 是由荷兰数学与计算机科学研究中心的吉多.范罗苏姆(Guido von Rossum)于1990年代初设计,作为对ABC语言的替代品。1989年圣诞节Guido开始编写Python语言的编辑器。2008年12月Python3.0发布。 优点 简单易学:Python在编程语言中比较适合新手学习,是一种…

rocky 安装gnome extension

rocky 9,没有任务栏,不好看,而且也不好用,每次切换应用都需要从左上角的 activity 处进入1. 首先需要安装 gnome.Extensions 可以通过 sudo yum install gnome-tweaks ,但是我试了,这个里面没有我想要配置的,可能需要更新新版本 2. 更新版本 需要安装 flatapk,参考 htt…

CSS Grid 布局

HTML:<body><div class="headTitle">常用的Grid布局</div><div class="layout"> <div class="box box1">box方块</div> <div class="box">box方块</div> <div class=&qu…

AT_abc379_g

-1过于一眼的轮廓线 dp。 兼纪念 abc 首场无伤 AK。 首先我们可以经过缜密的计算的得到矩形的宽不超过 \(14\)。然后现在你有 \(4\) 个数(边界视作 \(0\))。 不难想到 \(4\) 进制状压轮廓线 dp。轮廓线 dp 状压 dp 的一种,轮廓线是分隔已处理部分与未处理部分的线。 在本题中…

【Stata 18软件下载与安装教程 含密钥】

1、安装包Stata 18: 链接:https://pan.quark.cn/s/a34fb60dbe77 提取码:av8q 2、安装教程 1) 双击解压包内Setup.exe安装,弹窗安装对话框2) 点击下一步3) 选择I accept ,点击下一步4) 输入用户名,任意输入,点击Next5) 选择StataMP,点…

2024-2025-1 20241403 《计算机基础与程序设计》第七周学习总结

学期(如2024-2025-1) 学号(如:20241403) 《计算机基础与程序设计》第7周学习总结 作业信息这个作业属于哪个课程 <班级的链接>(如2024-2025-1-计算机基础与程序设计)这个作业要求在哪里 <作业要求的链接>(如2024-2025-1计算机基础与程序设计第一周作业)这个…

chapter17

malloc.py参数中文版第一题问题1.首先运行 flag -n 10 -H 0 -p BEST -s 0 来产生一些随机分配和释放。你能预测malloc()/free()会返回什么吗?你可以在每次请求后猜测空闲列表的状态吗?随着时间的推移,你对空闲列表有什么发现?空闲列表不会合并,导致外部碎片越来越多 第二…

29. 多线程编程

一、什么是线程线程(thread)它们是同一个进程下执行的,并共享相同的下上文。线程包括开始、执行顺序和结束三部分。它有一个指令指针,用于记录当前运行的上下文。当其它线程运行时,它可以被抢占(中断)和临时挂起(也称为睡眠)—— 这种做法叫做让步(yielding)。当一个…

2024-2025-1 学号 20241301 《计算机基础与程序设计》第七周学习总结

|这个作业属于哪个课程|2024-2025-1-计算机基础与程序设计 https://edu.cnblogs.com/campus/besti/2024-2025-1-CFAP| |这个作业要求在哪里|2024-2025-1计算机基础与程序设计第一周作业 https://edu.cnblogs.com/campus/besti/2024-2025-1-CFAP/homework/13276| |这个作业的目标…