c++枚举

本文介绍了C++中的枚举概念及其在解决算法问题中的应用。通过百鸡问题、拉格郎日四平方和定理及寻找特定完全平方十位数的案例,阐述如何使用枚举优化代码,减少循环层数并提高效率。同时强调在枚举过程中需要注意的时间复杂度和优化策略。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

枚举

1. 概念

枚举,顾名思义就是遍历每个可能答案,从所有的候选答案中去搜索正确的解,暴力的枚举所有可能。这个算法的优缺点也非常明显:
优点:通过循环就能够轻易实现,并且得到的结果总是正确的
缺点:非常暴力,而且速度可能很慢
学会这个算法非常简单,只需要会写for循环就可以了……
但是,通过这个缺点我们就可以知道,如果老老实实的把范围内的所有数都枚举一遍,也就是使用多重for循环是非常慢的,可能会导致TLE。所以枚举算法的核心就在于优化。一般来说,有两个大概的方向
减少枚举变量:如果枚举的变量满足一个关系式,那么循环可以少写一层
缩小枚举范围:对于不可能有正确答案的范围可以直接舍去

2. 例题

2.1 百鸡问题

2.1.1 题目

一只公鸡5元钱,一只母鸡3元钱,而1元可买3只小鸡。现有n元钱,想买n只鸡,问可买公鸡、母鸡、小鸡各几只?输出方案数。(n<=5000000)
(注意题目数据量,考虑时间复杂度)
样例输入:
100
样例输出:
4
时间限制:
1000
空间限制:
65536

2.1.2 分析

这题可以列出一个方程,设公鸡买i只,母鸡买j只,则小鸡买了(n-i-j)只,所以:
5i+3j+(n-i-j)/3=n,可以得到i与j的数量关系,循环也只用一层了。还有循环的结束条件也要优化哦

2.1.3 代码
#include<bits/stdc++.h>
using namespace std;
int main(){
	int n,ans=0;
	cin>>n;
	//7i+4j=n
	//j=(n-7i)/4
	for(int i=0;i<=n/7;i++){
		if((n-7*i)%4==0&&n>=7*i){
			ans++;
		}
	}
	cout<<ans;
	return 0;
}

注:两层循环就会TLE,更别说3层了

2.2 玩玩拉格郎日四平方和定理

2.2.1 题目

题目描述:
拉格朗日四平方和定理:
每一个非负整数都可以表示成四个非负整数的平方和。
例如 5 = 0^ 2 + 0^ 2 + 1^ 2 + 2^2
给定一个正整数n,请你将n拆成 a^ 2+b^ 2+c^ 2+d^2,问 a+b+c+d最小是多少。
输入格式:
一个正整数表示 n。
输出格式:
一个正整数表示答案。
样例输入1:
4
样例输出1:
2
约定:
1<=n<=90000

2.2.2 分析

这道题的方法也很明显,每个for循环枚举一个底数,注意0也是可以的。不过这里最多只能减到三层循环,就没办法优化了。每个for循环的循环次数照样是要减少的。枚举的过程中还要做比大小的操作。

2.2.3 代码
#include<bits/stdc++.h>
using namespace std;
int main(){
	int n,minn=99999;
	cin>>n;
	for(int i=0;i<=sqrt(n);i++){
		for(int j=0;j<=sqrt(n-i*i);j++){
			for(int k=0;k<=sqrt(n-i*i-j*j);k++){
				int l=sqrt(n-i*i-j*j-k*k);
				if(i*i+k*k+j*j+l*l==n&&i+j+k+l<minn){
					minn=i+k+j+l;
				}
			}
		}
	}
	cout<<minn;
	return 0;
}

2.3 平方十位数

2.3.1 题目

题目描述:
请找出最大的满足以下条件的十位数:
这个十位数由0~ 9组成,且0~9各出现一次。
这个十位数是一个完全平方数。
输入格式:

输出格式:
一个十位数表示答案。
样例输入1:

样例输出1:

约定:
由于本题的特殊性,本题只有一组测试数据。 为了训练自己的枚举水平,请不要直接提交直接输出答案的程序。
提示:
注意本题时间限制。

2.3.2 分析

看到约定,想偷懒骗分的是不是伤心了?
因为要求最大,我们循环就从最大开始,一旦找到了就return 0。因为这里要求的数是完全平方数,所以可以定义一个int的变量,从999999999的平方根开始到100000000的平方根。这个循环变量的平方如果就是这个数,那说明这个数是完全平方数,否则不是。接着需要考虑的是每个数字是否只出现了一次。可以定义标记的数组vis,记录每个数字出现了几次。如果sum是10,就说明符合条件,输出即可。

2.3.3 代码
#include<bits/stdc++.h>
using namespace std;
int main(){
	for(long long n=99381;n>=31990;n--){
		long long num=n*n;
		int vis[10]={},sum=0;
		while(num){
			vis[num%10]++;
			sum+=vis[num%10];
			num/=10;
		}
		if(sum==10){
			cout<<n*n;
			return 0;
		}
	}
	return 0;
}

由此可见,枚举的代码一般比较短,只需要for套for就可以了

制作不易,点个赞吧😘

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值