1.枚举算法介绍:
- 枚举算法是一种基本的算法思想,它通过穷举所有可能的情况来解决问题。它的基本思想是将问题的解空间中的每个可能的解都枚举出来,并进行验证和比较,找到满足问题条件的最优解或者所有解。
- 枚举算法适用于问题规模较小、解空间可穷举的情况。它的优点是简单直观,不需要复杂的数学推导,易于实现。但是,由于需要穷举所有可能的情况,对于问题规模较大的情况,枚举算法的时间复杂度可能会非常高,效率较低。
2.解空间的类型:
- 解空间可以是一个范围内的所有数字(或二元组、字符串等数据),或者满足某个条件的所有数字。
- 当然也可以是解空间树,一般可分为子集树和排列树,针对解空间树,需要使用回溯法进行枚举(在后面讲到搜索的时候会讲到)
目前仅使用循环去暴力枚举解空间,具体的解空间类型需要根据题目来理解构造。
3.循环枚举解空间:
1.首先确定解空间的维度,即问题中需要枚举的变量个数。
- 例如:当题目要求的是满足条件的数字时,我们可以循环枚举某个范围内的数字。如果要求的是满足条件的二元组,我们可以用双重循环分别枚举第一个和第二个变量,从而构造出一个二元组。
2.对于每个变量 确定其可能的取值范围。这些范围可以根据问题的性质和约束条件来确定。这一步往往是时间复杂度优化的关键。
3.在循环体内,针对每个可能解进行处理。可以进行问题的验证、计算、输出等操作
4.例题讲解:
题号:lanqiao OJ 191
1.特别数的和:
该题解空间:是1~n中所有的整数
#include<bits/stdc++.h>
using namespace std;
bool f(int x){while(x){int y=x%10;if(y==2||y==0||y==1||y==9){return true;}x/=10;}return false;
}
int main(){int n;cin>>n;int ans=0;for(int i=1;i<=n;++i){if(f(i)){ans+=i;}}cout<<ans<<'\n';return 0;
}
题号:lanqiao OJ 152
2.反倍数:
该题解空间:也是1~n中所有的整数
#include<bits/stdc++.h>
using namespace std;
int a,b,c;
bool f(int x){return x%a!=0&&x%b!=0&&x%c!=0;
}
int main(){int n;cin>>n;cin>>a>>b>>c;int ans=0;for(int i=1;i<=n;++i){if(f(i)){ans++;}}cout<<ans<<'\n';return 0;
}
题号:lanqiao OJ 3227
3.找到最多的数
使用map来存储该数字出现的次数
#include<bits/stdc++.h>
using namespace std;
map<int,int> mp;
int main(){int n,m;cin>>n>>m;for(int i=1;i<=m*n;++i){int x;cin>>x;mp[x]++;}for(const auto & [x,y] : mp){if(2*y>=n*m/2){cout<<x<<'\n';}}return 0;
}
###上述皆枚举所有数字(解空间),再加之判断是否满足条件