前言(随便看看)
当你夜深人静的时候,当你还在苦苦的使用搜索却无法看透问题的本质是,你可以试试这个宇宙无敌的搜索方式,没有花里胡哨,没有技巧,只有从头到尾的遍历+遍历,他就是无敌的枚举,是真的啥题都能做的玄学搜索,真的强的一批啊。
一、什么是枚举
在数学和计算机科学理论中,一个集的枚举是列出某些有穷序列集的所有成员的程序,或者是一种特定类型对象的计数。这两种类型经常(但不总是)重叠。是一个被命名的整型常数的集合,枚举在日常生活中很常见,例如表示星期的SUNDAY、MONDAY、TUESDAY、WEDNESDAY、THURSDAY、FRIDAY、SATURDAY就是一个枚举。
以上是百度给出的解释,但是太官方,要我说枚举就是你觉得有的、有可能有的、有的没的都尝试一遍,最后符合条件的就得出答案,因此,枚举也是最简单而且容错率最高的。但是,因为要遍历所有的数据,所以他的占存也是最高的,所以,一时枚举一时爽,超时直接火葬场。
二、枚举实践
此处使用网站为我们的好朋友洛谷
1.枚举的原理
首先,枚举是最基本的搜索,也是最万能的搜索,打个比方:一个方程x+2=10问x等于什么。正常人肯定说:当然是把方程变成x+2-2=10-2得出x=8,但是,电脑不会逆向思维啊,只能这样把x一直改变一直增加,最后总会得出答案比如把x从0一直加一,0,1,2,3,4……最后当x+2=10结束代码输出结果,这样就可以得出代码
int x=0;
while(x+2==10){
x++;
}
cout<<x;
所以,枚举就是类似愚公移山的原理一点一点的直到夷平大山。枚举就是这个原理,一步一步把所有的答案都试一遍,最后得出结果。
2.什么时候使用枚举
要满足以下两个条件:
- 是搜索类型的问题
- 在数据可以包含的范围内
- 是有意义的数据
只要满足这些条件,在复杂的问题都可以返璞归真,用简单的循环完成解题。但是注意:如果此时的数据量大到离谱,就不可以使用枚举,会超时,会溢出!!!
3.枚举的实例应用
首先,枚举你得知道你自己举什么,有的人写着写着代码,就忘了自己要举什么,最后直接秃头。所以,怎么知道自己要举什么呢?用个例子来看一下:洛谷P2241
先看代码:
#include<bits/stdc++.h>
long long n,m,i,j,sum=0,sum1=0;
using namespace std;
int main()
{
cin>>n>>m;
for(i=1;i<=n;i++){//遍历长的每一个格子
· for(j=1;j<=m;j++){//遍历宽的每一个格子
sum+=min(i,j);//求出当前最小的边长的大小做正方形的边长
sum1+=i*j;//长宽之积便是所有长方形+正方形的数量
}
}
cout<<sum<<" "<<sum1-sum<<endl;//排除长方形中的正方形,输出正方形
return 0;
}
这道题所举得就是长和宽的每一个格子,从一个格子举到n×m个格子,这里sum1得出的就是在这么大的格子中一共有多少个长方形不信自己去画图 ,这就叫枚举。但是注意这里的复杂度是n×m如果n,m≤50000000。咳咳恭喜你程序炸了。
由此可以看出枚举会超时,超很多,所以枚举不是万能的。
4.枚举的进阶
接下来看这道题:洛谷P3392
先看代码:
#include<iostream>
using namespace std;
char flat[51][51];
int n,m;
struct color{
int w;
int r;
int b;
};
color a[51];
int mun;
int main(){
cin>>n>>m;
for(int i=0;i<n;i++){
for(int j=0;j<m;j++){
cin>>flat[i][j];
}
}
for(int i=0;i<n;i++){//统计每一行红,白,蓝的数量
for(int j=0;j<m;j++){
if(flat[i][j]=='W'){
a[i].w++;
}else if(flat[i][j]=='B'){
a[i].b++;
}else{
a[i].r++;
}
}
}
int sum=0,small=0x7fffffff;//定义最小的数为最大值
for(int i=0;i<n-2;i++){
for(int j=i+1;j<n-1;j++){
sum=0;
for(int k=0;k<i+1;k++){
sum+=a[k].b+a[k].r;//统计从第一行到白色到最后一行白色要改变的颜色
}
for(int k=i+1;k<j+1;k++){
sum+=a[k].w+a[k].r;//同理蓝色
}
for(int k=j+1;k<n;k++){
sum+=a[k].b+a[k].w;//剩余全是白色
}
if(sum<small){
small=sum;//输出最少
}
}
}
cout<<small;
return 0;
}
这里这个需要遍历的就是每一个的颜色,统计每一种颜色不同的方式都尝试一遍,这就是枚举。
总结
如果你完成了上面写的所有题目并且自己时间过以后,那么恭喜你 离秃头 离一个成功的程序猿又近了一步。一看到搜索就用枚举是绝对不可行的,除非真的要用枚举,否者很容易超时!!!
最后刷完洛谷上的这个题单,你就可以完全的完成对枚举基础的学习:提单