枚举算法的优化(一) 生理周期

枚举算法的优化

我们先来看题目

生理周期
问题描述
人有体力、情商、智商的高峰日子,它们分别每隔 23天、28 天和33天出现一次。对于每个人,我们想知道何时三个高峰落在同一天。给定三个高峰出现的日子p,e和i(不一定是第一次高峰出现的日子),再给定另一个指定的日子d,你的任务是输出日子d之后,下一次三个高峰落在同一天的日子(用距离d的天数表示)。例如:给定日子为10,下次出现三个高峰同一天的日子是12,则输出2。
输入
输入四个整数: p,e,i和d。 p,e,i分别表示体力、情感和:智力高峰出现的日子。d是给定的日子,可能小于p,e或i。所有给定日子是非负的并且小于或等于365,所求的日子小于或等于21252。
输出
从给定日子起,下一次三个高峰同一天的日子D 的天数。

问题分析

这道题在于找到一个日子k,使得k满足同时可以整除23,28,33,即满足下面的式子

	(k - p) % 23 == 0 && (k - e) % 28 == 0 && (k - i) % 33 == 0

我们可以根据这个原理来设计以下程序

#include<iostream>
using namespace std;
int main() {
	int p, e, i, d;
	cin >> p >> e >> i >> d;
	if (d >= 0 && d <= 365)
	{
		for (int k = d + 1; k <= 21252; k++)
		{
			if ((k - p) % 23 == 0 && (k - e) % 28 == 0 && (k - i) % 33 == 0)
				cout << k - d << endl;
		}
	}
	else
		cout << "Error" << endl;
	system("pause");
	return 0;
}

问题的优化

在上述代码中,我们使用了枚举,让k从d+1天开始,一直到21252天,逐一实验直到找到合适的k,这样虽然能解决问题,但是逐一实验难免浪费了时间,我们知道有的天数不用实验,必然是不符合要求的,因此我们可以采取以下流程:
1.找到第一个可以整除p的k,即

	for (int k = d + 1; (k - p) % 23; k++); 

2.让k每次增加23,直到找到一个k,可以整除e,即

	for (; (k - e) % 28; k += 23);

3.让k每次增加23*28,直到找到一个k,可以整除i,即

	for (; (k - i) % 33; k += 23 * 28);

4.通过过以上三步,我们大大缩小了数字筛选的范围,减少尝试的次数,从而减小了程序运行的时间和占用的内存

优化后的程序

#include<iostream>
using namespace std;
int main() {
	int p, e, i, d;
	cin >> p >> e >> i >> d;
	if (d >= 0 && d <= 365)
	{
		int k;
		for (k = d + 1; (k - p) % 23; k++);
		for (; (k - e) % 28; k += 23);
		for (; (k - i) % 33; k += 23 * 28);
		cout << k - d << endl;
	}
	else
		cout << "Error" << endl;
	system("pause");
	return 0;
}

备注:问题转载自:https://www.icourse163.org/learn/PKU-1001894005?tid=1205957211#/learn/content?type=detail&id=1210422473&cid=1212471887

猜你喜欢

转载自blog.csdn.net/weixin_43699716/article/details/93409161
今日推荐