枚举+递归算法:计算24

Deadly 提交于 2020-01-30 03:51:00

问题描述:

给出4个小于10的正整数,可以使用+-*/()的运算将这4个数连接起来得到一个表达式。问,是否存在一种计算方式可以使表达式的结果为24。

输入:

输入多行数据,每行包括4个小于10的正整数。最后一行数据为4个0,作为数据的终止。

输出:

对于每一组数据,如果可以得到24,则输出“YES”,否则输出“NO”。

样例输入与输出:

5 5 5 1 

YES

1 1 4 2 

NO

0 0 0 0 

问题的分析及解决:

这个问题就是我们所熟知的算24这个数学游戏。我们先跳出如果用代码实现这个问题,思考一下,当给我们4个数字时,我们是用什么方式得出是否可以计算24这个问题。大部分人所用的方法都是连拼带凑的方法得出结论的,即尝试将几个数字进行+-*/运算,拼凑出是否为24。如果将这种思想转化为算法思想,我们首先想出的便是枚举,即把数字两两计算,并且把所有的可能性都列举出来,例如:我们已知A,B,C,D这4个数字,我们先尝试A,B;A,C;A,D;B,C;B,D;C,D这6组数的+-*/,并把这6组数得出的结果与剩下的值重复进行上述的操作,直至剩余最后2个数尝试进行+-*/,看看是否能够得出24这个值,如果最终的结果为24,那么输出YES,否则输出NO。

在编写代码的过程中,我们会发现,如果用非递归的方式写代码,将会嵌套好几层for循环,且代码显得非常的冗余,所以在循环重复计算时,我们引入递归的方式,减少冗余的代码量。且这题在解决多重循环的问题上,类似N皇后问题的处理方法。由于N皇后问题中的N参数未知,所以通过递归可以避免手写N重循环的问题。本题其实已知循环的层数了,可以通过递归来提升代码的简洁度。代码实现难度相对不大。

代码

#include <iostream>
#include <math.h>
using namespace std;
double a[5];//存储录入的4个参数
#define EPS 1e-6

bool isZero(double x)//判断是否为0
{
	return fabs(x) <= EPS;
}

bool Calculate24(double a[], int n)
{
	if (n == 1)
	{
		if (isZero(a[0] - 24))
			return true;
		else
			return false;
	}
	double b[5];//用于存数组a中未计算的参数及完成计算的参数的值
	for (int i = 0; i < n - 1; i++)
		for (int j = i + 1; j < n; j++)
		{
			int m = 0;
			for (int k = 0; k < n; k++)//将数组a中未计算的参数放入数组b中
				if (k != i && k != j)
					b[m++] = a[k];//m自增

			b[m] = a[i] + a[j];
			if (Calculate24(b, m + 1))
				return true;

			b[m] = a[i] - a[j];
			if (Calculate24(b, m + 1))
				return true;

			b[m] = a[j] - a[i];
			if (Calculate24(b, m + 1))
				return true;

			b[m] = a[i] * a[j];
			if (Calculate24(b, m + 1))
				return true;

			if (!isZero(a[i]))
			{
				b[m] = a[i] / a[j];
				if (Calculate24(b, m + 1))
					return true;
			}
			
			if (!isZero(a[j]))
			{
				b[m] = a[j] / a[i];
				if (Calculate24(b, m + 1))
					return true;
			}
		}
	return false;
}

void main()
{
	while (true)
	{
		for (int i = 0; i < 4; i++)
			cin >> a[i];
		if (isZero(a[0]))
			break;
		if (Calculate24(a, 4))
			cout << "YES" << endl;
		else
			cout << "NO" << endl;
	}
}

代码细节简评:

1)由于浮点数是不能用==来判断两个浮点数是否相等的,所以在这我们定义了一个isZero(double x)函数进行判断。通过2个浮点数相减绝对值小于 1e-16,来判断2个浮点数是否相等。

2)在进行除法时,我们要判断被除数是否为0

3)整体难度和思路的难度不算太大,但是码量有点大,撸的时候要细心一点。

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!