12-算24

对于递归的最后一个问题,我们来看一下稍微复杂点的问题,这里的思想仍然是将问题分解为规模更小的子问题。

1、问题描述

例题:算24
给出4个小于10个正整数,你可以使用加减乘除4种运算以及括号把这4个数连接起来得到一个表达式。现在的问题是,是否存在一种方式使得得到的表达式的结果等于24。这里加减乘除以及括号的运算结果和运算的优先级跟我们平常的定义一致(这里的除法定义是实数除法)。比如,对于5,5,5,1,我们知道5*(5–1/5)=24,因此可以得到24。又比如,对于1,1,4,2,我们怎么都不能得到24。

输入
输入数据包括多行,每行给出一组测试数据,包括4个小于10个正整
数。最后一组测试数据中包括4个0,表示输入的结束,这组数据不用
处理。
输出
对于每一组测试数据,输出一行,如果可以得到24,输出“YES”;
否则,输出“NO”。

样例输入
5 5 5 1
1 1 4 2
0 0 0 0
样例输出
YES
NO

2、问题分析

有 n 个数计算24,计算过程肯定是有两个数先算出结果,用这个结果再和剩下的 n-2 个数计算,于是问题变成了 n-1 个数求24的问题。我们可以
枚举需要先计算的两个数,计算这两个数所有可能的计算结果。

边界条件:什么时候计算结束呢,就是最后就剩下一个数了,这个数是24,成功,不是24,失败。

这里有一个问题,除法的结果是个浮点数,这里涉及到了比较浮点数是否相等的问题,不能直接用==,因为有些位上的数据可能省略了,应该用两数相减小于某个较小的值来决定是否相等。

#include<iostream>
using namespace std;
#define EPS 1e-6
double a[4];

bool iszero(double x)
{
	return fabs(x) <= EPS;
}
//用数组a中的n个数计算24
bool count24(double a[], int n)
{
	if (n == 1)							//只有一个数了
	{
		if (iszero(a[0] - 24))
			return true;
		else
			return false;
	}
	double b[4];
	for (int i = 0; i < n-1; i++)
		for (int j = i + 1; j < n; j++)	//枚举两个数的组合
		{
			int m = 0;					//还剩下n-2个数
			for (int k = 0; k < n; k++)
				if (k != i && k != j)
					b[m++] = a[k];		//把其余的数放到b中

			b[m] = a[i] + a[j];			//两数两乘的结果也放b中
			if (count24(b, n - 1))
				return true;
			b[m] = a[i] - a[j];
			if (count24(b, n - 1))
				return true;
			b[m] = a[j] - a[i];
			if (count24(b, n - 1))
				return true;
			b[m] = a[j] * a[i];
			if (count24(b, n - 1))
				return true;
			if (!iszero(a[j]))			//分母不是0,才进行除法运算
			{
				b[m] = a[i] / a[j];
				if (count24(b, n - 1))
					return true;
			}
			if (!iszero(a[i]))
			{
				b[m] = a[j] / a[i];
				if (count24(b, n - 1))
					return true;
			}	
		}
	return false;
}

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

abs,fabs,fabsf的使用

int abs(int i); //处理int类型的取绝对值
double fabs(double i); //处理double类型的取绝对值
float fabsf(float i); //处理float类型的取绝对值
fabs是取绝对值,但abs是取绝对值后再取整。

3、总结

  1. 浮点数比较是否相等,不能用 ==
  2. 将问题分解为规模更小的子问题
非常抱歉,我之前的回答有误。你是正确的,47 经过操作后的步骤应该是 8 次,而不是 7 次。 让我们再次检查代码和操作过程: ``` candies = int(input()) minCount = [sys.maxsize] divide(candies, 0, minCount) print(minCount[0]) ``` 对于输入的 47,程序进入 `divide(47, 0, minCount)`。 1. 47 是奇数,所以执行 `else` 分支: - 执行 `divide(48, 1, minCount)`:将糖果数量加一,并将操作次数加一。 2. 48 是偶数,所以执行 `if` 分支: - 执行 `divide(24, 2, minCount)`:将糖果数量除以2,并将操作次数加一。 3. 24 是偶数,所以执行 `if` 分支: - 执行 `divide(12, 3, minCount)`:将糖果数量除以2,并将操作次数加一。 4. 12 是偶数,所以执行 `if` 分支: - 执行 `divide(6, 4, minCount)`:将糖果数量除以2,并将操作次数加一。 5. 6 是偶数,所以执行 `if` 分支: - 执行 `divide(3, 5, minCount)`:将糖果数量除以2,并将操作次数加一。 6. 3 是奇数,所以执行 `else` 分支: - 执行 `divide(4, 6, minCount)`:将糖果数量加一,并将操作次数加一。 7. 4 是偶数,所以执行 `if` 分支: - 执行 `divide(2, 7, minCount)`:将糖果数量除以2,并将操作次数加一。 8. 2 是偶数,所以执行 `if` 分支: - 执行 `divide(1, 8, minCount)`:将糖果数量除以2,并将操作次数加一。 9. 1 是终止条件,进入 `if candies == 1` 分支: - 更新 `minCount[0]` 为当前操作次数 `count` 的较小值,即 8。 因此,最小操作次数是 8,而不是 7。非常抱歉给你带来了困惑。如果还有其他问题,请随时提问。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值