c++枚举详解
枚举
什么是枚举
枚举算法是我们在日常中使用最多的一种算法思想,它的核心思想是:枚举所有的可能,确定枚举对象、范围和判定条件;然后注意枚举可能的解并验证每个解是否是问题的解。
枚举的结构:
循环+判断语句。
枚举算法的优点
- 枚举算法一般是现实生活问题的“直译”,所以比较直观,易于理解
- 枚举算法建立在考察大量状态、甚至是穷举所有状态的基础上,所有算法的真确性容易证明
枚举算法的缺点
枚举算法的效率取决与枚举状态的数量和单个状态枚举的代价,所以枚举效率比较低
枚举的例题
例题1:数字统计
请统计某个给定范围\([L,R]\)的所有整数中,数字2出现的次数
比如给定范围[2, 22],数字 2 在数 2 中出现了 1 次,在数 12 中出现 1 次,在数 20 中出现 1 次,在数 21 中出现 1 次,在数 22 中出现 2 次,所以数字 2 在该范围内一共出现了 6次。
输入格式:
输入共 1 行,为两个正整数 L 和 R,之间用一个空格隔开。
输出格式:
输出共 1 行,表示数字 2 出现的次数。
输入样例 2 22 输出样例 6
思路:我们可以直接枚举范围\([L,R]\)中的每一个数,观察这个数中有几个数字\(2\)。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define endl '\n'
#define IOS ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
int n, m, res;
int main(){
IOS
cin >> n >> m;
for(int i = n; i <= m; i++){
int temp = i;
while(temp){
if(temp % 10 == 2) res++;
temp /= 10;
}
}
cout << res << endl;
return 0;
}
例题2:百钱白鸡
公鸡五元一只,母鸡三元一只,小鸡三只一元,现在你有一百元要买一百只鸡,问公鸡、母鸡、小鸡各多少买多少只。
思路,这题的数据范围很小,我们可以逐个枚举,一共买\(100\)只鸡,每种鸡买的范围为\([ 0,100 ]\)于是我们可以对三种鸡分别列举\(0\)到\(100\)种可能.
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define endl '\n'
#define IOS ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
int res;
int main(){
IOS
for(int i = 0; i <= 100; i++){
for(int j = 0; j <= 100; j++){
for(int k = 0; k <= 100; k++){
if(i + j + k == 100 && 15 * i + 9 * j + k == 300)
cout << i << " " << j << " " << k << endl;
}
}
}
return 0;
}
我们可以继续观察这个问题的代码,我们发现,这样的计算有很多多余的猜测,导致时间的消耗很大,为了减少多余的猜测,可以在已列举的情况下,不断排除空间内已不满足的解。由于公鸡是\(5\)元一只,所以公鸡最多可以买\(20\)只,同理母鸡最多可以买\(33\)只。又由于只买\(100\)只鸡,在枚举了前两种鸡的个数之后,第三只鸡的个数也已经得到了\(=100-i-j\)。因此我们就没有必要在进行枚举了。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define endl '\n'
#define IOS ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
int res;
int main(){
IOS
for(int i = 0; i <= 20; i++){
for(int j = 0; j <= 33; j++){
int k = 100 - i - j;
if(15 * i + 9 * j + k == 300)
cout << i << " " << j << " " << k << endl;
}
}
return 0;
}
枚举算法的优化
- 枚举算法的时间复杂度:状态总数 \(\times\)单个状态的耗时。
- 主要优化方法:
减少状态总数;
降低单个状态的考察代价。 - 优化过程从以下几个方面考虑:
枚举对象的选取;
枚举方法的确定;
采用局部枚举或引进其他算法。