基础算法--枚举

枚举算法是一种简单而有效的算法,它通过枚举所有可能的情况来解决问题。它通常用于解决问题规模比较小的问题,因为它的时间复杂度很高,随着问题的规模增加,算法的效率会急剧下降。

枚举算法的基本思路是通过循环遍历所有可能的情况,找到最优解或满足条件的解。它的步骤通常包括:

1.选择一个变量作为枚举变量,并确定它的取值范围。

2.在循环过程中遍历所有可能的取值,并执行某种操作。

3.检查每个可能的解是否符合要求,如果符合要求就记录下来。

4.在所有可能的解中,选择最优解或满足特定条件的解。

枚举作为一个基础的算法,除了与模拟算法有着密不可分的关系,还对解决一些线性表的问题有很大帮助。在解决线性表的问题中,枚举分为:线性枚举、二分枚举、三分枚举。在算法中,又可以分为暴力枚举(穷举法)、排列组合枚举、状压DP。这些算法都有其特定的适用场景和优缺点,需要根据具体的情况选择合适的算法。

叽里咕噜一大堆,今天带你认识一下各种词汇,别被它的名字给吓到,也许有些知识你学过但是你并不知道它的官方叫法而已。


一、线性枚举

简介:

线性枚举指的是遍历某一个一维数组(顺序表)的所有元素,找到满足条件的那个元素并且返回,返回的可以是下标,也可以是元素本身。由于是遍历的,穷举了所有情况,所以一定是可以找到解的,除非问题本身无解。一些资料上也称之为暴力算法(Brute Force)

练习:

给出一个数组:int* arr[10]={3,6,2,5,8,9,7,4,1,0};要求找到7所在位置的下标是多少。

int fuc(int* arr,int n,int targ){//arr={......};n=10;targ=7for(int i=0;i<n;i++){if(arr[i]==targ)return i;}return NULL;
}

总结: 

线性模拟就是循环遍历的一种叫法,时间复杂度O(n),认识即可。ok~技能树成功点亮了一叶。

二、二分枚举

简介:

如果在顺序表是有序的情况下,我们可以采取折半的方法去查找,这种方法称为二分枚举。

二分传送门:查找算法--二分查找-CSDN博客

练习:

洛谷2440-木材加工(这道题在上面传送的那个文章中讲过)

木材厂有 𝑛 根原木,现在想把这些木头切割成 𝑘k段长度为 𝑙的小段木头(木头有可能有剩余)。当然,我们希望得到的小段木头越长越好,请求出 𝑙的最大值。木头长度的单位是 cm,原木的长度都是正整数,我们要求切割得到的小段木头的长度也是正整数。

例如有两根原木长度分别为 11和 21,要求切割成等长的 6 段,很明显能切割出来的小段木头长度最长为 5。

#include<vector>
#include<algorithm>
#include<iostream>using namespace std;
int maxLength(vector<int> v, int k)
{//二分的前提是顺序表有序sort(v.begin(), v.end());int m = v[v.size()-1];int left = 0;int right = m;int mid = (right - left) / 2 + left;while (left < right){if (right-left == 1) {//如果木段差==1,就该考虑返回left还是返回rightint s = 0; for (auto e : v) {s += (e / right);}if (s >= k)return right;//如果总段数大于k说明至少能截成k个right.return left;//没能进入返回}int sum = 0;//段数和for (auto e : v) {//每根原木的长度÷估计的最大段长->可截段数//每根原木的可截段数 求总和sum += (e / mid);}//二分if (sum >= k) {//根据中值求总段数,可以获得比标准数量更多的小木段//那么可以试着大一点,更新左值left = mid;}else if (sum < k) {//根据中值不能获取足够的小木段//那么可以试着小一点,更新右值right = mid-1;}mid = (right - left) / 2 + left;//中值--更新mid}//时间复杂度O(nlogn),此时n为最短元素大小return mid;//结果理论为:left==mid==right
}
int main()
{int N, K; //N原木个数,K目标段数cin >> N >> K;vector<int> v(N);for (int i = 0; i < N; i++)cin >> v[i];//每根原木长度cout << maxLength(v, K) << endl;return 0;
}

总结:

这就是我们的二分法,时间复杂度为O(logn)。是不是又是一个熟悉的知识点。掌握了就在这个知识点的后面打上√吧。

三、三分枚举

简介:

三分枚举是一种用于求解单峰(单谷)函数极值的算法。它的基本原理是利用函数的单峰(单谷)性质,通过迭代的方式逐步缩小搜索范围,最终找到极值点。具体来说:对于形如y=ax²+bx+c的二次函数,其极值点位于x=-b/2a。如果给定一个包含极值点的区间,可以通过三分法逐步缩小区间范围,直到找到极值点。

练习:

牛客练习赛59-C.装备合成

牛牛有x件材料a和y件材料b,用2件材料a和3件材料b可以合成一件装备,用4件材料a和1件材料b也可以合成一件装备。牛牛想要最大化合成的装备的数量,于是牛牛找来了你帮忙。


输入包含t组数据
第一行一个整数t
接下来t行每行两个整数x,y

每组数据输出一行一个整数表示答案。

假设方案一做了m件装备,方案二做了n件装备,我们遍历m来求n,n=min((x-2m)/4, y-3m),三分m,求n+m的最大值

由于三分时返回的m+n是整数,注意下面的情况时check(mid1)==check(mid2)&&check(mid1)<check(R) ,L=mid1+1,而不是R=mid2-1

#include <bits/stdc++.h>
using namespace std;int x, y;
int check(int m){return m+min((x-2*m)/4, y-3*m);
}
int main(){   int T;cin>>T;while(T--){cin>>x>>y;int L=0, R = min(x/2, y/3);int ans = 0;while(L<=R){int mid1 = L+(R-L)/3, mid2 = R-(R-L)/3;int res1 = check(mid1), res2 = check(mid2);ans = max(res1, res2);if(res1<res2||(res1==res2&&res1<check(R))) L = mid1+1;else R = mid2-1;}cout<<ans;}return 0;
}

 总结:

三分枚举算法常用于求解优化问题,特别是在没有明显规律可循的环境中。例如,在处理山峰高度调整问题时,可以通过三分枚举算法来最小化山峰之间的最大高度差。具体应用场景包括但不限于调整山峰高度、优化资源配置等。

三分枚举算法的优点在于其简单易懂,适用于求解单峰(或单谷)函数的极值问题。然而,它的缺点也很明显,即效率较低,特别是在处理大规模数据时,可能会消耗较多的计算资源。此外,三分枚举算法依赖于函数的单峰(或单谷)性质,如果函数不满足这一性质,算法将无法正确工作。


四、暴力枚举

简介:

暴力枚举,顾名思义,就是将问题的所有可能解逐一列举出来,然后一一验证,直到找到正确解。这种方法虽然看似粗暴,但对于规模较小的问题或者没有更优解法的情况下,往往是最直接有效的方法。数组的线性枚举就是暴力枚举的一种。

练习:

X星系的机器人可以自动复制自己。它们用1年的时间可以复制出2个自己,然后就失去复制能力。
每年X星系都会选出1个新出生的机器人发往太空。也就是说,如果X星系原有机器人5个,
1年后总数是:5 + 9 = 14
2年后总数是:5 + 9 + 17 = 31
如果已经探测经过n年后的机器人总数s,你能算出最初有多少机器人吗?


输入:输入一行两个数字n和s,用空格分开,含义如上。n不大于100,s位数不超过50位。
输出:要求输出一行,一个整数,表示最初有机器人多少个。

从有一个开始试,试到n年,看此时的结果是不是输入的总人数。是就输出并退出,不是的话就继续。今年能产生的机器人数量=去年的*2-1。然后把今年产生的加在总count里。判断count和输入的一不一样。

#include <iostream>
using namespace std;#define Long long long
int main() {int n;Long total,count = 0;Long thisYear=0,lastYear=0 ;cin >> n >>total;for (int i = 1; i < total; ++i) {count = thisYear = i;for (int j = 0; j < n; ++j) {lastYear = thisYear;thisYear = lastYear*2-1;count += thisYear;}if (count == total) {cout << i;return 0;} //else continue;}
}

 五、排列组合枚举

简介:

1. 排列枚举:给定 n 个元素,枚举其所有的 r 元素排列可以使用递归或回溯的方法。

2. 组合枚举:同样地,组合的枚举也可以使用递归的方式来实现。

递归传送门:基础算法--递归算法【难点、重点】-CSDN博客

练习:

生成给定数组的所有排列组合:

#include <iostream>  
#include <vector>  
#include <algorithm>  
using namespace std;void permute(vector<int>& nums, int start) {  if (start == nums.size() - 1) {  // 输出当前排列  for (int num : nums) {  cout << num << " ";  }  cout << endl;  } else {  for (int i = start; i < nums.size(); ++i) {  swap(nums[start], nums[i]); // 交换  permute(nums, start + 1);        // 递归  swap(nums[start], nums[i]); // 撤销交换  }  }  
}  void combine(const vector<int>& nums, int r, int start, vector<int>& path) {  if (path.size() == r) {  // 输出当前组合  for (int num : path) {  cout << num << " ";  }  cout << endl;  return;  }  for (int i = start; i < nums.size(); ++i) {  path.push_back(nums[i]); // 添加当前元素  combine(nums, r, i + 1, path); // 递归  path.pop_back(); // 撤销添加  }  
}  int main() {  vector<int> vec = {1, 2, 3};  permute(vec, 0);  vector<int> nums = {1, 2, 3};  int r = 2; // 组合的大小  vector<int> path;  combine(nums, r, 0, path);  return 0;  
}
  • 排列枚举: 这个程序通过交换当前元素和其他元素的位置,然后递归处理下一个位置,最终列出所有可能的排列。
  • 组合枚举: 这个程序通过递归构建组合,每次选择当前元素并继续下一次迭代。通过 path 存储当前组合,达到组合大小后输出结果。

六、状压DP

em,我还没学,不太会,就不讲了。谅解谅解,嘻嘻。


感谢观看!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/880973.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

CSS实现服务卡片

CSS实现服务卡片 效果展示 CSS 知识点 回顾整体CSS知识点灵活运用CSS知识点 页面整体布局 <div class"container"><div class"card"><div class"box"><div class"icon"><ion-icon name"color-pal…

记录一次病毒启动脚本

在第一次下载软件时&#xff0c;目录中配了一个使用说明&#xff0c;说是需要通过start.bat 这个文件来启动程序&#xff0c;而这个 start.bat 就是始作俑者&#xff1a; 病毒作者比较狡猾&#xff0c;其中start.bat 用记事本打开是乱码&#xff0c;但是可以通过将这个批处理…

OpenMV与STM32通信全面指南

目录 引言 一、OpenMV和STM32简介 1.1 OpenMV简介 1.2 STM32简介 二、通信协议概述 三、硬件连接 3.1 硬件准备 3.2 引脚连接 四、软件环境搭建 4.1 OpenMV IDE安装 4.2 STM32开发环境 五、UART通信实现 5.1 OpenMV端编程 5.2 STM32端编程 六、SPI通信实现 6.1 …

查缺补漏----I/O中断处理过程

中断优先级包括响应优先级和处理优先级&#xff0c;响应优先级由硬件线路或查询程序的查询顺序决定&#xff0c;不可动态改变。处理优先级可利用中断屏蔽技术动态调整&#xff0c;以实现多重中断。下面来看他们如何运用在中断处理过程中&#xff1a; 中断控制器位于CPU和外设之…

动态规划最长上升子序列问题讲解和【题解】——最长上升子序列

动态规划最长上升子序列讲解和题解——最长上升子序列 最长上升子序列问题讲解1.概念解析2.举例了解3.示例程序 最长上升子序列题目描述输入格式输出格式输入输出样例输入 #1输出 #1 提示思路解析 最长上升子序列问题讲解 1.概念解析 最长上升子序列 &#xff08; L o n g e s…

微服务sentinel解析部署使用全流程

sentinel源码地址&#xff1a; 介绍 alibaba/Sentinel Wiki GitHub sentinel官方文档&#xff1a; https://sentinelguard.io/zh-cn/docs/introduction.html Sprong Cloud alibaba Sentinel文档【小例子】 : Sentinel alibaba/spring-cloud-alibaba Wiki GitHub 目录 1、…

C# + SQLiteExpert 进行(cipher)加密数据库开发+Costura.Fody 清爽发布

一&#xff1a;让 SQLiteExpert 支持&#xff08;cipher&#xff09;加密数据库 SQLiteExpert 作为SQlite 的管理工具&#xff0c;默认不支持加密数据库的&#xff0c;使其成为支持&#xff08;cipher&#xff09;加密数据库的管理工具&#xff0c;需要添加e_sqlcipher.dll &…

Android-Handle消息传递和线程通信

本文为作者学习笔记&#xff0c;如有误&#xff0c;请各位大佬指点 目录 一、同步异步 二、Java多线程通信 三、Handler是什么 四、Handler相关的类 五、Handler常用方法 1. 发送消息 2. 接收处理消息 3. 切换线程 六、使用Handler 使用Handler更新UI 使用Handler延…

蓝桥杯【物联网】零基础到国奖之路:十八. 扩展模块之光敏和AS312

蓝桥杯【物联网】零基础到国奖之路:十八.扩展模块之光敏和AS312 第一节 硬件解读第二节 CubeMX配置第二节 代码 第一节 硬件解读 光敏和AS312如下图&#xff1a; 光敏电阻接到了扩展模块的5号引脚&#xff0c;5号引脚接了2个电阻&#xff0c;R8和光敏电阻。我们通过ADC读取这…

Python 从入门到实战33(使用MySQL)

我们的目标是&#xff1a;通过这一套资料学习下来&#xff0c;通过熟练掌握python基础&#xff0c;然后结合经典实例、实践相结合&#xff0c;使我们完全掌握python&#xff0c;并做到独立完成项目开发的能力。 上篇文章我们讨论了数据库编程接口操作的相关知识。今天我们将学习…

ASP.NET Zero 多租户介绍

ASP.NET Zero 是一个基于 ASP.NET Core 的应用程序框架&#xff0c;它提供了多租户支持&#xff0c;以下是关于 ASP.NET Zero 多租户的介绍&#xff1a; 一、多租户概念 多租户是一种软件架构模式&#xff0c;允许多个客户&#xff08;租户&#xff09;共享同一套软件应用程序…

探索TOGAF理论的实践应用:企业数字化转型的深度指南

数字化转型的迫切性与路径选择 随着全球化进程和技术革命的加速&#xff0c;企业正面临前所未有的挑战和机遇。数字化转型已成为企业保持竞争力、创新业务模式、优化客户体验的核心手段。然而&#xff0c;企业在实施数字化转型时&#xff0c;往往面临路径不清、技术与业务脱节…

《Linux从小白到高手》理论篇(七):Linux的时间管理运行级别启动过程原理详解

List item 本篇将介绍Linux的时间管理&运行级别相关知识&#xff0c;并将深入介绍Linux的启动过程及原理。 Linux的时间管理 Linux 时钟分为系统时钟&#xff08;System Clock&#xff09;和硬件&#xff08;Real Time Clock&#xff0c;简称 RTC&#xff09;时钟。系统时…

Linux驱动开发(速记版)--设备树插件

第六十八章 设备树插件介绍 Linux 4.4之后引入了动态设备树&#xff0c;其中的设备树插件&#xff08;Device Tree Overlay&#xff09;是一种扩展机制&#xff0c;允许在运行时动态添加、修改或删除设备节点和属性。 设备树插件机制通过DTS&#xff08;设备树源文件&#xff0…

protobuf 讲解

一、序列化概念回顾 二、什么是PB 将结构化数据进行序列化的一种方式 三、PB的特点 语言无关、平台无关&#xff1a;即PB支持Java&#xff0c;C、Python等多种语言。支持多个平台 高效&#xff1a;即比XML更小&#xff0c;更快&#xff0c;更为简单。 扩展性、兼容性好&am…

WPF之UI进阶--控件样式与样式模板及词典

WPF的优势之一就是能够更加容易快捷的对窗体和控件的外面进行改造&#xff0c;换句话说&#xff0c;那就是UI设计个性化更加容易。主要是借助了样式、模板及词典来实现的。那么本篇博文就一一对他们进行介绍。 文章目录 一、样式1: 定义样式2: 使用Setter设置属性关于Property和…

C或C++判断指针是否指向同一块内存

有时需要判断指针是否指同一块内存&#xff0c;例如设计字符串时&#xff1a; &#xff08;1&#xff09;insert函数 &#xff08;2) replace函数 &#xff08;3&#xff09;assign函数 难点是迭代器&#xff0c;判断是否同一个迭代器时&#xff0c;需要你在设计迭代器时加…

Kubernetes-环境篇-01-mac开发环境搭建

1、brew安装 参考知乎文章&#xff1a;https://zhuanlan.zhihu.com/p/111014448 苹果电脑 常规安装脚本&#xff08;推荐 完全体 几分钟安装完成&#xff09; /bin/zsh -c "$(curl -fsSL https://gitee.com/cunkai/HomebrewCN/raw/master/Homebrew.sh)"苹果电脑 极…

Rstudio:强大的R语言集成开发环境(IDE)

Rstudio 应该是 R 语言使用的标配&#xff0c;尽管 Rstudio 的母公司 Posit 推出了新一代的集成开发环境 Positron&#xff0c;但其还处于开发阶段。作为用户不妨让其成熟后再使用&#xff0c;现阶段还是 Rstudio 更稳定。 如果你在生物信息学或统计学领域工作&#xff0c;R语言…

Python | Leetcode Python题解之第455题分发饼干

题目&#xff1a; 题解&#xff1a; class Solution:def findContentChildren(self, g: List[int], s: List[int]) -> int:g.sort()s.sort()m, n len(g), len(s)i j count 0while i < m and j < n:while j < n and g[i] > s[j]:j 1if j < n:count 1i …