题目描述
总时间限制: 3000ms 内存限制: 65536kB
描述
给出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
解题分析
将初始的4个数算24转化为较小规模的3个数算24,...,最后转化为一个数字算24,也就是是否是24的问题。转换方式就是,在原来n个数中挑选2个数,采用四则运算,因为有括号的存在,不用考虑运算谁优先的问题,然后再将运算结果和前面n-2个数合在一起,对n-1个数进行同样的操作。
解题代码
#include <iostream>
#include <cmath>
#define EPS 1e-6
using namespace std;
double a[5];
bool isZero(double a){
return fabs(a) < EPS;
}
bool count24(double a[], int n);
int main(){
while( cin >> a[0] >> a[1]>> a[2] >> a[3] && !isZero(a[0]))
{
if(count24(a, 4)){
cout << "YES"<<endl;
}
else
cout << "NO"<<endl;
}
return 0;
}
bool count24(double a[], int n){
if(n == 1){
if(isZero(a[0] - 24))
return true;
else
return false;
}
double b[5];
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++){ //将剩下的数b复制到b[]数组中,并加上取出的两个数的计算结果
if(k != i && k != j)
b[m++] = a[k];
}
b[m] = a[i] + a[j];
if(count24(b, m+1))
return true;
b[m] = a[i] - a[j];
if(count24(b, m + 1))
return true;
b[m] = a[j] - a[i];
if(count24(b, m + 1))
return true;
if(!isZero(a[j])){
b[m] = a[i]/ a[j];
if (count24(b, m + 1)){
return true;
}
}
if(!isZero(a[i])){
b[m] = a[j]/ a[i];
if(count24(b, m + 1))
return true;
}
b[m] = a[i] * a[j];
if(count24(b, m + 1))
return true;
}
}
return false;
}