首页 > 其他分享 >位运算的妙用:状态压缩动态规划

位运算的妙用:状态压缩动态规划

时间:2023-12-30 18:55:39浏览次数:39  
标签:妙用 10000 运算 状态 压缩 合法 ij 兼容 dp

原理讲解

   状态压缩DP其实就是把一种状态通过二进制的形式储存下来,从而利于进行状态的转移。
   例如5个盒子排成一排,其中第1,3,4个盒子有糖果,那么可以表示为 \(10110\) 转换为十进制就是 \(22\) 。

这类问题通常有一定的模板,在以下情况可能要用到状压DP:

  • 所输入的内容只有两种状态,就比如只有 \(1\) 和 \(0\) 。
  • 统计合法状态的方案数 or 最大值。
  • 不能用其他方法。

  解决这类问题的状态一般都设置为如 \(dp_{ij...}\) ,其中 \(i\) 表示第几排/个,\(j\) 表示第 \(i\) 排/个 的状态,如果有其它条件的话可能还需要扩展维度。其状态转移方程一般也类似于 \(dp_{ij}+=dp_{i-1k}\) \(cnt\) 表示合法状态数,当然,其最终答案就类似于 \(\sum_{i=1}^{cnt} dp_{ni}\) ,这肯定不是绝对的,具体还要看是求数量|最大值,还是别的。

  那么,状压DP有什么缺点呢?其实也很容易发现:即使是长整型 long long 也只有64位,也就是说最多只能存64和状态,这真是一个致命缺点

例题解析

  理论会了,就开始实践吧!
  来看这题 Corn Fields G,这题可以说是超超超经典的一道状压DP题。首先,也是这题的关键,就是将土地状态转化为十进制储存,如将111转化为7。要计算方案总数,那一要先判断那种状态是合法的,判断一种状态是否合法要考虑三个问题,行内合法以,行间兼容,和是否在肥沃的土壤上,也就是这一步体现了题目所说的"位运算的妙用"。

行内兼容

举个栗子:在 \(0000_2 到 1111_2\)中共有8种合法状态 \(0000,0001,0010,0100,0101,1000,1001,1010\),要怎么筛选出它们呢?回忆一下 & 运算符的运算规则:相同为1否则为零,再往深了想一下是不是只要 i&(i>>1)=0 ,就表明状态 i是合法的?就比如 1010&0101=0。是不是豁然开朗了。 i&(i<<1)=0也是可以的。

行间兼容

有了前面的经验的经验这个就简单了,只要 i$j=0第 \(i\) 行就和第 \(j\) 行相兼容,就比如说 1010&0100=0这两行就可以兼容。

是否在肥沃的土壤上

这个也很好理解,完成这一步骤还是要用到 &运算。
我们来找一下规律:
\(10010\&10000=10000,01100\&10000=0,00000\&10000=0\)
\(10010\&11111=100100,01100\&111111=01100,00000\&11111=0\)
  你发现了什么?没错对于土地状态 i和当前状态j 只要 i&j==j,那么状态j就是OK的。


这样就可以愉快的设计算法了:

  • 定义 \(dp_{ij}\) 为第i行第j种状态的方案数。
  • 初始状态 \(dp_{1i}=1\),即第1行的每种状态都是一种方案
  • 状态转移方程 \(dp_{ij}+=dp_{i-1k}\)
  • 最终答案 \(\sum_{i=1}^{cnt} dp_{ni}\)

参考代码

#include<bits/stdc++.h>
using namespace std;
const int mod=100000000;
int num[13],dp[13][1<<13],ans=0;
int g[1<<13];
int main()
{
	int n,m;
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;i++){
		for(int j=1;j<=m;j++){
			int tmp; cin>>tmp;
			num[i]=(num[i]<<1)+tmp;
	    }
	}
	for(int i=0;i<(1<<m);i++){
		if(!(i&(i>>1))&&!(i&(i<<1))){
			g[i]=1;
			if((i&num[1])==i) 
			dp[1][i]=1;
		}
	}
	for(int x=2;x<=n;x++){
		for(int j=0;j<(1<<m);j++){	
			if(((j&num[x-1])==j)&&g[j]==1){
				for(int y=0;y<(1<<m);y++){
					if(((y&num[x])==y)&&!(j&y)&&g[y]){
					dp[x][y]=(dp[x][y]+dp[x-1][j])%mod;
					}
				}
			}	
		}	
	}
	for(int i=0;i<(1<<m);i++)
		ans=(ans+dp[n][i])%mod;
	printf("%d\n",ans);
    return 0;
}

更多题目

互不侵犯
炮兵阵地
Matching
Mixed Up Cows G

标签:妙用,10000,运算,状态,压缩,合法,ij,兼容,dp
From: https://www.cnblogs.com/demc/p/17936659.html

相关文章

  • FineReport动态隔间运算
    1、动态隔间运算入门说明首先提供一个公式,公式:“显示列[显示列的父列:偏移量]”。此时你不需要知道这个公式是什么意思,目前有个印象就行,通过下面的学习你就明白了。动态隔间运算类似于EXCEL表格中的公式运算,相当于你在某个单元格中输入“=…”这样的公式。定义不太好叙述,下面......
  • 结合 element -Plus组件库,压缩图片大小,限制图片格式
    业务背景:业务上需求满足上传的图片不能太大,但是有时候上传的图片确实超过了限制大小,所以前端这边可以将图片压缩再上传,亦或者是上传给后端接口的图片只能是指定格式,我们前端需要将图片后缀转化,也可以处理!封装的使用方法如下:使用canvas对图片进行压缩处理:/**压缩图片......
  • linux 中 压缩、解压缩、查看gz文件保留源文件
     001、压缩为gz文件,同时保留源文件[root@pc1test]#lsa.txt[root@pc1test]#gzip-ca.txt>a.txt.gz##压缩文件,同时保留源文件[root@pc1test]#lsa.txta.txt.gz 002、解压缩gz文件保留源文件[root@pc1test]#lsa.txt.gz[root@pc1test]#gunzip-c......
  • 利用ImageMagick进行图片压缩
    1.安装ImageMagicksudoapt-getupdatesudoapt-getinstallimagemagick2.图片压缩基本指令#-monitor显示进度#-fuzz5%颜色容差(colorfuzzfactor)#-layersOptimize对图层进行优化处理convert-monitortimeline05.gif-fuzz5%-layersOptimizemagick_timeli......
  • nginx支持br压缩
    项目使用Brotli压缩算法来减小传输数据的大小。要启用Brotli压缩算法,确定是否支持broti模块:nginx-V2>&1|grep-owith-http_brotli_module如果输出中包含了"with-http_brotli_module",则表示您的Nginx版本支持Brotli模块。没有则需要安装;安装libbrotlicd/www/servergitclon......
  • H5前端特殊艺术字体文件太大,可通过font-spider压缩
    原理:1.爬行本地html文档,分析所有css语句2.记录@font-face语句声明的字体,并且记录使用该字体的css选择器3.通过css选择器的规则查找当前html文档的节点,记录节点上的文本4.找到字体文件并删除没被使用的字符5.编码成跨平台使用的字体格式简而言之:就是爬出你项目中......
  • C# 范围运算符
    a.. 等效于 a..^0..b 等效于 0..b.. 等效于 0..^0范围运算符表达式说明..集合中的所有值。..end从开头到 end(不含)的值。start..从 start(含)到结尾的值。start..end从 start(含)到 end(不含)的值。^start..从 start(含)到倒计数结尾的值。..^e......
  • 轻量级力量:深入MiniZip库,实现C++中ZIP文件的简便压缩与解压
     MiniZip是一个轻量级的压缩库,它是zlib库的一部分,用于在C++中进行ZIP文件的压缩和解压缩操作。以下是MiniZip的一些功能和优点:功能:创建ZIP文件: MiniZip可以用于创建包含一个或多个文件的ZIP归档。压缩: MiniZip支持使用不同的压缩算法对文件进行压缩,例如DEFLATE。解压缩......
  • 数据类型转换&表达式&运算符总结
    总结数据类型转换概念:将数据从一种格式或结构转换为另一种格式或结构的过程。作用:节约内存空间将一些类型转换为项目所需要的类型类型转换分类自动隐式转换定义:将小的数据类型转换大的数据类型注意事项:在Java中,boolean类型与所有其他7种类型都不能......
  • UPX 可执行文件压缩工具的介绍与使用
    UPX是什么UPX全称是"UltimatePackerforeXecutables",是一个免费、开源、编写、可扩展、高性能的可执行程序打包程序。换句话说一个可执行文件的压缩工具。主要的功能是将可执行的二进制程序、动态链接库和其他的二进制文件压缩为更小的体积,UPX通常可以将文件大小减少50%......