状压DP之子集枚举总结

状压DP之子集枚举总结

一、子集枚举的暴力与优化方案

在状压DP中,我们采用二进制 maskmaskmask 表示元素的选择状态。若要枚举某个状态 maskmaskmask 的所有子集,暴力方案需通过两层循环遍历所有可能的二进制数,再通过(s & t) == t判断t是否为s的子集,该方式时间复杂度极高,核心代码如下:

cpp 复制代码
for(int s=0;s<(1<<n);s++){
    for(int t=0;t<(1<<n);t++){
        if((s&t)==t){
            // t是s的子集
        }
    }
}

优化方案借助位运算实现高效枚举,能大幅降低时间复杂度,核心代码为:

cpp 复制代码
for(int s=0;s<(1<<n);s++){
    for(int t=s;t;t=(t-1)&s){
        // t是s的子集
    }
}

其核心逻辑为:对当前子集 ttt 先减 111 (使二进制数变小),再与原状态 sss 做与运算。减1操作会将t最低位的 111 变为 000,其右侧所有 000 变为 111;与 sss 做与运算可抹去新增的、原状态s中不存在的1,保证结果仍是 sss 的子集。以二进制数 (10110)2(10110)_2(10110)2 为例,按此逻辑可依次枚举得到(10100)2(10100)_2(10100)2、(10010)2(10010)_2(10010)2、(10000)2(10000)_2(10000)2、(110)2(110)_2(110)2、(100)2(100)_2(100)2、(10)2(10)_2(10)2等所有非空子集。

二、子集枚举的理论依据

  1. 子集合法性:根据与运算&的性质,若 a<ba < ba<b ,则 a&ba \& ba&b 的结果二进制中所有1出现的位置在b的二进制对应位置均为 111,因此结果必为 bbb 的子集(如1010&101101=10001010 \& 101101 = 10001010&101101=1000)。先对 ttt 减 111 再与 sss 做与运算,既让子集对应的数字变小,又保证了结果是原状态 sss 的子集。
  2. 无遗漏枚举:子集枚举本质是在原集合的二进制状态下将部分1换为0。减1后做与运算,会逐次将当前子集的最低位1置0,同时抹去新增的、原状态中不存在的1,能够遍历原集合的所有子集,且从s本身开始枚举,确保无遗漏。

三、复杂度证明

假设集合大小为nnn:

  1. 若某个mask包含kkk个1,则该mask有2k2^k2k个子集;
  2. 包含kkk个1的mask共有组合数(nk)\binom{n}{k}(kn)种;
  3. 总操作次数为求和式:∑k=0n(nk)2k\sum_{k=0}^{n} \binom{n}{k} 2^k∑k=0n(kn)2k。

根据二项式定理(x+y)n=∑(nk)xkyn−k(x+y)^n = \sum \binom{n}{k} x^k y^{n-k}(x+y)n=∑(kn)xkyn−k,令x=2x=2x=2、y=1y=1y=1,可得:
∑k=0n(nk)2k⋅1n−k=(2+1)n=3n\sum_{k=0}^{n} \binom{n}{k} 2^k \cdot 1^{n-k} = (2+1)^n = 3^n∑k=0n(kn)2k⋅1n−k=(2+1)n=3n。

因此,枚举所有状态的所有子集的时间复杂度为O(3n)O(3^n)O(3n),相较于暴力枚举的O(4n)O(4^n)O(4n)大幅优化,使得nnn的取值可达到15~16左右。

相关推荐
v_348360876214 小时前
Android native端 堆栈打印
android·算法
residual_fan14 小时前
【学术论文】航空发动机故障诊断智能体:基于持续对比强化学习的动态优化方法
人工智能·算法·数据挖掘·数据分析
老当益壮梁奶奶14 小时前
51单片机DS18B20温度传感器详解:单总线时序与C51驱动实现
笔记·stm32·单片机·嵌入式硬件·51单片机
GG-_-Bond15 小时前
9.1 kv存储resp协议模拟面试
c++
GreenTea15 小时前
OpenAI Agents API 上手实测:一次调用把整个 agent loop 甩给 OpenAI
前端·后端·算法
米糕闯编程15 小时前
鱼香ros2(五)用C++编写节点
c++·ros2·cmakelists·鱼香
小叶肥辉15 小时前
LangChain链和LangGraph图的学习笔记【三】——分别用langchain_openai库和langchain_community库调用大模型
笔记·python·langchain
深圳满意度咨询16 小时前
医院满意度数字化测评系统:从数据采集到智能决策的技术实践
算法
xiangyun6116 小时前
【408数据结构 08】队列:循环队列判空判满,408年年考,一次讲清
c语言·开发语言·数据结构·c++·算法
xiangyun6117 小时前
【408数据结构 06】双链表、循环链表、静态链表
c语言·开发语言·数据结构·c++·算法