C++暴力搜索(枚举)使用方法


前言(随便看看)

当你夜深人静的时候,当你还在苦苦的使用搜索却无法看透问题的本质是,你可以试试这个宇宙无敌的搜索方式,没有花里胡哨,没有技巧,只有从头到尾的遍历+遍历,他就是无敌的枚举,是真的啥题都能做的玄学搜索,真的强的一批啊。


一、什么是枚举

在数学和计算机科学理论中,一个集的枚举是列出某些有穷序列集的所有成员的程序,或者是一种特定类型对象的计数。这两种类型经常(但不总是)重叠。是一个被命名的整型常数的集合,枚举在日常生活中很常见,例如表示星期的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.什么时候使用枚举

要满足以下两个条件:

  1. 是搜索类型的问题
  2. 在数据可以包含的范围内
  3. 是有意义的数据

只要满足这些条件,在复杂的问题都可以返璞归真,用简单的循环完成解题。但是注意:如果此时的数据量大到离谱,就不可以使用枚举,会超时,会溢出!!!

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;
}

这里这个需要遍历的就是每一个的颜色,统计每一种颜色不同的方式都尝试一遍,这就是枚举。


总结

如果你完成了上面写的所有题目并且自己时间过以后,那么恭喜你 离秃头 离一个成功的程序猿又近了一步。一看到搜索就用枚举是绝对不可行的,除非真的要用枚举,否者很容易超时!!!
最后刷完洛谷上的这个题单,你就可以完全的完成对枚举基础的学习:提单

  • 6
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

辰星墨韵

第一次写文章,有错误请海涵。

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值