1789:算24
总时间限制: 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
#include
using namespace std;
double d[4];//四个整数,因为实数除法,干脆小数
bool ans,//最后结果,
k[4];//那个已经用过,还有结果存在数组哪个位置中
bool in(){//只有4个0时,输入结束
bool k=0;
for(int i=0;i<4;i++){
cin>>d[i];k=k||d[i];
}
return k;
}
void go(int x){
if(x3){//四个数三次运算,0,1,2。x3运算完结
for(int i=0;i<4;i++)
if(!k[i])//运算结果存在唯一没有标记的位置中
if(d[i]>23.9&&d[i]<24.1){//四个整数,实数除法,结果等于24,没说23.9到24.1,坑
ans=1;
}
return;
}
if(ans)return;//有一组正确答案就不用再找了,终结递归,不再扩散
double a,b;//第三变量,便于回溯
for(int i=0;i<4;i++)//遍历所有数
if(!k[i])//只有没有标记过的可以存结果。也可以说是已经优先计算的括号内结果。最多两个括号。(7-3)(5+1)=46=24
for(int j=i+1;j<4;j++)//当前数和剩下的数计算
if(!k[j]){//没标记过,参与计算
a=d[i],b=d[j];
k[j]=1;//标记用了
d[i]=a+b;go(x+1);//存在没标记的i位置。
d[i]=a-b;go(x+1);//存差
d[i]=b-a;go(x+1);//a有可能是运算结果,b也可能是,如(7-3)(5+1)
d[i]=ab;go(x+1);
d[i]=a/b;go(x+1);
d[i]=b/a;go(x+1);
d[i]=a;//回溯,恢复该步以前状态
k[j]=0;//取消标记
}
}
int main(){
//freopen(“data.cpp”,“r”,stdin);
while(in()){
ans=0;
go(0);
if(ans)cout<<“YES\n”; else cout<<“NO\n”;
}
return 0;
}