news 2026/3/22 22:45:24

算法——枚举

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
算法——枚举

一、普通枚举

P1003 [NOIP 2011 提高组] 铺地毯 - 洛谷

题目描述

为了准备一个独特的颁奖典礼,组织者在会场的一片矩形区域(可看做是平面直角坐标系的第一象限)铺上一些矩形地毯。一共有 n 张地毯,编号从 1 到 n。现在将这些地毯按照编号从小到大的顺序平行于坐标轴先后铺设,后铺的地毯覆盖在前面已经铺好的地毯之上。

地毯铺设完成后,组织者想知道覆盖地面某个点的最上面的那张地毯的编号。注意:在矩形地毯边界和四个顶点上的点也算被地毯覆盖。

输入格式

输入共 n+2 行。

第一行,一个整数 n,表示总共有 n 张地毯。

接下来的 n 行中,第 i+1 行表示编号 i 的地毯的信息,包含四个整数 a,b,g,k,每两个整数之间用一个空格隔开,分别表示铺设地毯的左下角的坐标 (a,b) 以及地毯在 x 轴和 y 轴方向的长度。

第 n+2 行包含两个整数 x 和 y,表示所求的地面的点的坐标 (x,y)。

输出格式

输出共 1 行,一个整数,表示所求的地毯的编号;若此处没有被地毯覆盖则输出-1

输入输出样例

输入 #1复制

3
1 0 2 3
0 2 3 3
2 1 3 3
2 2

输出 #1复制

3

输入 #2复制

3
1 0 2 3
0 2 3 3
2 1 3 3
4 5

输出 #2复制

-1

说明/提示

【样例解释 1】

如下图,1 号地毯用实线表示,2 号地毯用虚线表示,3 号用双实线表示,覆盖点 (2,2) 的最上面一张地毯是 3 号地毯。

【数据范围】

对于 30% 的数据,有 n≤2。
对于 50% 的数据,0≤a,b,g,k≤100。
对于 100% 的数据,有 0≤n≤104, 0≤a,b,g,k≤105。

noip2011 提高组 day1 第 1 题。

思路:从后往前枚举所有的地毯,判断是否覆盖题目中给的点。

#include<iostream> using namespace std; const int N=1e5+10; int x[N],y[N],len_x[N],len_y[N]; int solve(int n,int a,int b) { while(n) { if(a>=x[n] && a<=(x[n]+len_x[n]) && b>=y[n] && b<=(y[n]+len_y[n])) return n; n--; } return -1; } int main() { int n; cin>>n; for(int i=1;i<=n;i++) cin>>x[i]>>y[i]>>len_x[i]>>len_y[i]; int a,b; cin>>a>>b; int ret=solve(n,a,b); cout<<ret; return 0; }

二、二进制枚举

1.子集

LCR 079. 子集 - 力扣(LeetCode)

给定一个整数数组nums,数组中的元素互不相同。返回该数组所有可能的子集(幂集)。

解集不能包含重复的子集。你可以按任意顺序返回解集。

示例 1:

输入:nums = [1,2,3]输出:[[],[1],[2],[1,2],[3],[1,3],[2,3],[1,2,3]]

示例 2:

输入:nums = [0]输出:[[],[0]]

提示:

  • 1 <= nums.length <= 10
  • -10 <= nums[i] <= 10
  • nums中的所有元素互不相同

二进制枚举:用一个数二进制表示中的0/1表示两种状态,从而达到枚举各种情况。
·利用二进制枚举时,会用到一些位运算的知识。不熟悉同学需要去补一下位运算相关的知识。
·关于用二进制中的0/1表示状态这种方法,会在动态规划章节中的状态压缩dp中继续使用到。
·二进制枚举的方式也可以用递归实现,后续递归课程中会再讲到。

解法:利用二进制枚举的方式,把所有情况都枚举出来。
用0表示不选某一位的数,用1表示选择某一位的数。

思路:

1.枚举0~1<<n-1之间所有的数。
2.枚举枚举的数中二进制表示中1的位置,把相应的数选出来。

class Solution { public: vector<vector<int>> subsets(vector<int>& nums) { vector<vector<int>> ret; int n=nums.size(); //枚举所有状态 for(int st=0;st<(1<<n);st++) { //存当前选的子集 vector<int>tmp; for(int i=0;i<n;i++) { //如果右移i位的结果末尾是1,就选择 if((st>>i)&1) tmp.push_back(nums[i]); } ret.push_back(tmp); } return ret; } };

2.P10449 费解的开关 - 洛谷

题目描述

你玩过“拉灯”游戏吗?

25 盏灯排成一个 5×5 的方形。

每一个灯都有一个开关,游戏者可以改变它的状态。

每一步,游戏者可以改变某一个灯的状态。

游戏者改变一个灯的状态会产生连锁反应:和这个灯上下左右相邻的灯也要相应地改变其状态。

我们用数字 1 表示一盏开着的灯,用数字 0 表示关着的灯。

下面这种状态

10111 01101 10111 10000 11011

在改变了最左上角的灯的状态后将变成:

01111 11101 10111 10000 11011

再改变它正中间的灯后状态将变成:

01111 11001 11001 10100 11011

给定一些游戏的初始状态,编写程序判断游戏者是否可能在 6 步以内使所有的灯都变亮。

输入格式

第一行输入正整数 n,代表数据中共有 n 个待解决的游戏初始状态。

以下若干行数据分为 n 组,每组数据有 5 行,每行 5 个字符。

每组数据描述了一个游戏的初始状态。

各组数据间用一个空行分隔。

输出格式

一共输出 n 行数据,每行有一个小于等于 6 的整数,它表示对于输入数据中对应的游戏状态最少需要几步才能使所有灯变亮。

对于某一个游戏初始状态,若 6 步以内无法使所有灯变亮,则输出-1

输入输出样例

输入 #1复制

3 00111 01011 10001 11010 11100 11101 11101 11110 11111 11111 01111 11111 11111 11111 11111

输出 #1复制

3 2 -1

说明/提示

测试数据满足 0<n≤500。

性质
1.每一盏灯,最多只会点一次,对于一盏灯而言,只有按或者不按两种状态。
2.按法的先后顺序,是不影响最终结果的。不用关心按的顺序,只用关心按了什么。
3.第一行的按法确定之后,后续灯的按法就跟着确定了,《扫雷》

解法:
1.暴力枚举第一行所有的按法;
2.根据第一行的按法,计算出当前行以及下一行被按之后的结果;
3.根据第一行的结果,推导出第二行的按法:重复2/3过程
4.直到按到最后一行,然后判断所有灯是否全亮。

如何实现这个解法?

1.如何枚举出第一行所有的按法呢?

用二进制枚举所有的状态st,0~(1<<5)-1。

2.如何计算出,一共按了多少次?

计算二进制表示中,有多少个1。

3.用二进制表示,来存储灯的初始状态

存的时候,把0->1,把1->0,此时,题目就从全亮变成全灭。

4.如何根据push这个按法,计算出当前行a[i]以及下一行a[i+1]被按之后的状态?

可以用位运算的知识,快速计算出被按之后的状态。

1)如果按照00100这个按法,将就将方框里的数字由0变1,由1变0。

2)正好就是 x ^ 1 ,因为 1 ^ 0 = 1 ,1 ^ 1 = 0 。

3)ai = ai ^ push ^ ( push << 1 ) ^ ( push >> 1 )

^ push : 把当前这个开关的二进制表示由1变0,由0变1

^ push << 1 :把左边这个开关的二进制表示由1变0,由0变1

^ push >> 1 :把右边这个开关的二进制表示由1变0,由0变1

4)如果push最高位是1,如果左移的话,会向高位移动,会把 a [ i ] 最高位下一位(红色圈)修改成1。但这一位是无效的位置,我们存储位置时,只要在前五位存储即可,所以要把这一位清空。

a [ i ] = a [ i ] & ( ( 1 << n ) -1 )

a [ i ] = 1 0 1 11

1<<n-1:1 1 1 1 0

result : 1 0 1 10

正好把多余的1变成0了。

5)下一行被按后的状态:

a [ i + 1 ] = a [ i + 1 ] ^ push

5.如何求出下一行怎末按?

next_push=a [ i ]

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/3/22 22:35:19

【C++】二叉搜索树

&#xff0c;二叉搜索树的概念 二叉搜索树又称二叉排序树&#xff0c;它或者是⼀棵空树&#xff0c;或者是具有以下性质的⼆叉树: • 若它的左⼦树不为空&#xff0c;则左⼦树上所有结点的值都⼩于等于根结点的值。 • 若它的右⼦树不为空&#xff0c;则右⼦树上所有结点的值…

作者头像 李华
网站建设 2026/3/14 22:01:15

企业级应用中处理API连接失败的5个真实案例

快速体验 打开 InsCode(快马)平台 https://www.inscode.net输入框内输入如下内容&#xff1a; 开发一个案例库应用&#xff0c;收集和展示各种API连接失败的解决方案。功能包括&#xff1a;1. 案例分类&#xff08;网络问题、认证问题、配置问题等&#xff09;&#xff1b;2.…

作者头像 李华
网站建设 2026/3/13 14:25:59

LightOnOCR-1B:终极OCR引擎,10亿参数5倍速解析

LightOnOCR-1B&#xff1a;终极OCR引擎&#xff0c;10亿参数5倍速解析 【免费下载链接】LightOnOCR-1B-1025 项目地址: https://ai.gitcode.com/hf_mirrors/lightonai/LightOnOCR-1B-1025 导语&#xff1a;LightOn推出的10亿参数OCR专用模型LightOnOCR-1B-1025&#xf…

作者头像 李华
网站建设 2026/3/13 12:50:36

对比:传统vs容器化SQL Server安装效率

快速体验 打开 InsCode(快马)平台 https://www.inscode.net输入框内输入如下内容&#xff1a; 创建一个SQL Server容器化部署工具&#xff0c;功能&#xff1a;1.自动拉取官方Docker镜像 2.生成自定义docker-compose.yml 3.配置持久化存储 4.设置资源限制 5.集成健康检查。支…

作者头像 李华
网站建设 2026/3/12 13:45:02

腾讯Hunyuan-4B-FP8:256K上下文+高效智能体大模型

腾讯Hunyuan-4B-FP8&#xff1a;256K上下文高效智能体大模型 【免费下载链接】Hunyuan-4B-Instruct-FP8 腾讯开源混元高效大语言模型系列成员&#xff0c;专为多场景部署优化。支持FP8量化与256K超长上下文&#xff0c;具备混合推理模式与强大智能体能力&#xff0c;在数学、编…

作者头像 李华
网站建设 2026/3/20 8:20:11

POTPLAYER快捷键大全:提升操作效率300%

快速体验 打开 InsCode(快马)平台 https://www.inscode.net输入框内输入如下内容&#xff1a; 开发一个POTPLAYER快捷键训练应用&#xff0c;功能包括&#xff1a;1. 分类展示所有快捷键&#xff08;播放控制、音量调节、画面处理等&#xff09;&#xff1b;2. 交互式练习模式…

作者头像 李华