简易状态压缩DP

博客介绍了如何利用位运算进行状态压缩动态规划(状压DP)。通过位运算的左移、右移、与、或、非等操作,简化状态表示,并通过实例展示了如何用位运算枚举子集。接着,提供了李白打酒问题和SGU 223国王问题的题解,阐述了如何应用状压DP解决这类问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

简易状压DP

开头甩定义
借助二进制完成对状态的压缩,从而进行动态规划的过程,我们称之为状态压缩动态规划(简称“状压DP”)

位运算

  1. 左移右移
    左移:左移一位,等价于该数x2
    eg. 110<<1 = 1100 (十进制从6变为12)
    右移同理
    eg. 110>>1 = 11(十进制从6变为3)

  2. 与或非
    相信各位OIer应当在普及时就学过位运算了,但本蒟蒻还是要讲
    与:按位进行与运算 满足两数同一位都为1时结果为1,否则为0
    或:按位进行或运算 满足两数同一位都为0时结果为0,否则为1
    非:按位取反

  3. 简单运算
    当我们需要判断或修改二进制数S的第i位时,我们进行以下操作
    若判断第i位是否为0 即判断 (S&(1<<i)) 是否为0
    若要将第i位设置为1 即 (S|(1<<i)) 即1左移i位于S进行或运算
    若要将第i位设置为0 即 (S&~(1<<i)) 即S与只有第i位为0的数进行或运算

  4. 简单应用
    经过上面的学习大家可以发现我们可以用位运算的方法来枚举子集
    假设集合A={1,2,3,4,5}
    我们可以通过将A中的数编号的方式使其转化为一个二进制数
    是不是非常神奇呀
    下面我们来康康具体操作
    假设我们要表示A的子集B={2,4,5}

二进制数位 4 3 2 1 0
二进制值 1 1 0 1 0
子集元素 5 4 0 2 0

这里需要注意的是二进制的数位是从0开始的,所以对应关系不要找错
所以B集合用二进制就可以表示为11010啦!!

那么我们来做个练习

李白打酒 【2014蓝桥杯预赛】
话说大诗人李白,一生好饮。
一天,他提着酒壶,从家里出来,酒壶中有酒两斗。他边走边唱:
无事街上走,提壶去打酒
逢店加一倍,遇花喝一斗。
这一路上,他一共遇到店5次,遇到花10次,已知最后一次遇到的是花,他正好把酒喝光了。请你计算李白有多少种满足要求的遇到店和花的可能情况
输入

正确输出
14

题解:
一道简单的练手题
考虑使用01串表示遇到花或者店,因为最后一个一定是花所以枚举14位01串就OK
代码放送~

#include <bits/stdc++.h>
using namespace std;
int main()
{
   
	int ans=0;
	for(int i=0;i<(1<<14);i++)//枚举每种情况
	{
   
		int ans1=0,ans2=0;
		int num
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值