枚举
枚举是基于逐个尝试答案的一种问题求解策略。
基本思想:
- 建立简洁的数学模型
- 减小搜索空间
- 采用合理的搜索顺序
枚举算法是利用计算机快速的处理能力,对某一问题的每一种可能的解进行遍历、查找的方法。枚举算法实现起来相对简单,代码量短,并且容易理解,是相对基础的一种算法。
实现枚举算时有两点需要注意:一是要保证枚举了每一种情况,不会有遗漏的情形发生,这是枚举算法正确性的保证;二是在枚举时要保证每种情形只枚举一次,尽量避免重复的计算,这样才能保证时间复杂度在可以接受范围内。
同时,对于实际问题,也要学会分析枚举算法的效率,并对具体的算法进行一定的优化,尽可能地减少不必要的计算。例如,当前枚举的所有情况中的最好结果都不可能比已有结果更优时就可以直接退出。类似这样的优化还有很多。
总而言之,对于一个问题,如果没有很好的求解方法,那么不妨尝试枚举算法。
例如:求小于N的最大素数
-找不到一个数学公式,使得根据N就可以计算出这个素数
-N-1是素数吗?N-2是素数吗?
-判断N-i是否是素数的问题
-转化为求小于N的全部素数(可以用筛法)
例题1:完美立方
形如a3= b3 + c3 + d3的等式被称为完美立方等式。例如123= 63 + 83 + 103 。编写一个程序,对任给的正整数N (N≤100),寻找所有的四元组(a, b, c, d),使得a3 = b3 + c3 + d3,其中a,b,c,d 大于 1, 小于等于N,且b<=c<=d。
输入
一个正整数N (N≤100)。
输出
每行输出一个完美立方。输出格式为:
Cube = a, Triple = (b,c,d)
其中a,b,c,d所在位置分别用实际求出四元组值代入。
请按照a的值,从小到大依次输出。当两个完美立方等式中a的值相同,则b值小的优先输出、仍相同则c值小的优先输出、再相同则d值小的先输出。
样例输入
24
样例输出
Cube = 6, Triple = (3,4,5)
Cube = 12, Triple = (6,8,10)
Cube = 18, Triple = (2,12,16)
Cube = 18, Triple = (9,12,15)
Cube = 19, Triple = (3,10,18)
Cube = 20, Triple = (7,14,17)
Cube = 24, Triple = (12,16,20)
解题思路: 四重循环枚举a,b,c,d,a在最外层,d在最里层,每一层都是从小到大枚举,
a的枚举范围[2,N]
b的枚举范围[2,a-1]
c的枚举范围[b,a-1]
d的枚举范围[c,a-1]
#include <iostream>
#include <algorithm>
using namespace std;
int main() {
int n;
cin>>n;
for(int a=2; a<=n; a++)
for(int b=2; b<a; b++)
for(int c=b; c<a; c++)
for(int d=c; d<a; d++)
if(a*a*a==b*b*b+c*c*c+d*d*d) {
cout<<"Cube = "<<a<<", "<<"Triple = "<<"("<<b<<","<<c<<","<<d<<")"<<endl;
}
return 0;
}
例题2:生理周期 POJ1006
人生来就有三个生理周期,分别为体力、感情和智力周期,它们的周期长度为23天、28天和33天。每一个周期中有一天是高峰。在高峰这天,人会在相应的方面表现出色。例如,智力周期的高峰,人会思维敏捷,精力容易高度集中。因为三个周期的周长不同,所以通常三个周期的高峰不会落在同一天。对于每个人,我们想知道何时三个高峰落在同一天。对于每个周期,我们会给出从当前年份的第一天开始,到出现高峰的天数(不一定是第一次高峰出现的时间)。你的任务是给定一个从当年第一天开始数的天数,输出从给定时间开始(不包括给定时间)下一次三个高峰落在同一天的时间(距给定时间的天数)。例如:给定时间为10,下次出现三个高峰同天的时间是12,则输出2(注意这里不是3)。
输入:
输入四个整数:p, e, i和d。 p, e, i分别表示体力、情感和智力高峰出现的时间(时间从当年的第一天开始计算)。d 是给定的时间,可能小于p, e, 或 i。 所有给定时间是非负的并且小于365, 所求的时间小于21252。
当p = e = i = d = -1时,输入数据结束。
输出:
从给定时间起,下一次三个高峰同天的时间(距离给定时间的天数)。
采用以下格式:
Case 1: the next triple peak occurs in 1234 days.
注意:即使结果是1天,也使用复数形式“days”。
样例输入:
0 0 0 0
0 0 0 100
5 20 34 325
4 5 6 7
283 102 23 320
203 301 203 40
-1 -1 -1 -1
样例输出:
Case 1: the next triple peak occurs in 21252 days.
Case 2: the next triple peak occurs in 21152 days.
Case 3: the next triple peak occurs in 19575 days.
Case 4: the next triple peak occurs in 16994 days.
Case 5: the next triple peak occurs in 8910 days.
Case 6: the next triple peak occurs in 10789 days.
解题思路:
从d+1天开始,一直试到第21252天,对其中每个日期k,看是否满足:
(k - p)%23 == 0 && (k - e)%28 == 0 && (k - i)%33 == 0
在判断这个高峰时间是不是情商高峰时间;不是就将体力高峰时间增加23(也就是下一个体力高峰时间)
如果是情商高峰时间(说明也是体力高峰时间);
也是先判断是不是智商高峰时间;不是就将智商个体力高峰时间增加23*28(也就是下一个情商个体力高峰时间);
#include <iostream>
using namespace std;
int main() {
int p,e,i,d;
int num = 1;
while(cin>>p>>e>>i>>d&&p!=