[Acwing蓝桥杯搜索] 1243. 糖果
题目链接:1243. 糖果 - AcWing题库
题目大意:有n列m行 每行有k个数(k可能重复) 求最少选多少行可以覆盖所有的列
数据范围:1<=n<=100,1<=m,k<=20
数据范围非常小 最多有20列 枚举这20列可以用状态压缩
题目分析:
这是个重复覆盖问题。
重复覆盖指的是:列可以重复选,最后结果 一个列可能选多次
精确覆盖指的是:列不可以重复选,最后结果 一个列只能选一次 ,比如说:数独
最快做法:Dancing links(比较难,不会)
这个题用比较好写的写法:暴搜求最小值
1、搜索顺序
以此找到所有未被覆盖的列 所满足的行 直到所有的列都覆盖掉
或者某列 无法满足 无解
2、剪枝优化
(1)迭代加深 答案是1、答案是2... 一个个枚举判断
(2)找选择行最少的列
(3)可行性剪枝 采用估价函数
(4)将重复的行删掉
估价函数 h( )当前至少要选多少行才可以覆盖所有列 是个极限的情况
h( )与剩下的行比较 若h( )大于剩下的行 无解
(1)和(3)合称:IDA*优化
代码如下:
#include <cstring> #include <iostream> #include <algorithm> #include <vector> using namespace std; const int N=110,M=1<<20; int n,m,k; vector<int>cols[N];//cols[i]存i列为1的所有行的状态,即行状态含有第i列 int log2[M];//初始化log2数组 ,ps:如果用万能头就不能这样命名了 //和lowbit函数配合使用 求出最后一个所在列 需要初始化 int lowbits(int x) { return x&-x; } //估价出 最少的极限情况 int h(int state) { int res=0; for(int i=(1<<m)-1-state;i;i-=lowbits(i)) { int c=log2[lowbits(i)]; res++; //由于求极限 就要把所有含有c列的行都包含进去 //这里是细节技巧,由于状态i中还选的列相应的压缩状态为1 //row中的已经选的列压缩状态为1 //要将row中相应的列在状态i中标为0,表示已经选了 //可以将row先取反再与i相与 //row中的1取反变为0与i相与将i中的该位也变为0 //row中的0取反变为1与i相与不改变i中位的状态 for(auto row:cols[c])i&=~row; } return res; } bool dfs(int depth,int state) { //如果没有可选择的深度或者深度小于估价出的最小的方案数,直接判断返回是否覆盖完 if(!depth||h(state)>depth)return state==(1<<m)-1; //找出选择行最少的列t int t=-1; for(int i=(1<<m)-1-state;i;i-=lowbits(i)) { //依次枚举出所有的未被选择的列 int c=log2[lowbits(i)]; if(t==-1||cols[t].size()>cols[c].size()) { t=c; } } //找出列后依次dfs出该列的所有行的情况 for(auto row : cols[t]) if(dfs(depth - 1, state | row)) return true; return false; } int main() { cin>>n>>m>>k; //初始化log2数组 for(int i=0;i<m;i++)log2[1<<i]=i; for(int i=0;i<n;i++) { int state=0; //存state的k个列所在位置 for(int j=0;j<k;j++) { int c; cin>>c; state|=1<<c-1;//状态压缩 从0开始,下标减1 } //将state存放在所对应的列后边 for(int j=0;j<m;j++) { if(state>>j&1) { cols[j].push_back(state); } } } //剪枝:将列的 重复的行删掉 for(int i=0;i<m;i++) { sort(cols[i].begin(),cols[i].end()); cols[i].erase(unique(cols[i].begin(),cols[i].end()),cols[i].end()); } int depth=0;//枚举答案 也就是迭代加深 while(depth<=m&&!dfs(depth,0))depth++; if(depth>m)depth=-1; cout<<depth<<endl; return 0; }
end!!!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】