题目大意:给定4个数字,从1~13,可以调换顺序,使用+,-,*,/,(),五种运算符使得最后结果为24,判断是否可行。
解题思路:思路很简单的一道题,直接暴力枚举就可以了,但是枚举过程中要注意一些细节的处理
tip:1.“/”表示的就是数学中的除法并不取整。
2.要注意在枚举过程中出现0的情况的处理技巧,0是不能做分母的。
3,.不要忽略扩号,休想用调整四个数字的顺序的方式来代替括号的使用。例如a/(b+c)*d,你就不可能不加括号来实现。
详见代码:
#include <iostream>
#include <cstring>
#include <algorithm>
#include <cstdio>
#include <cmath>
using namespace std;
const double INF=0x3f3f3f3f;
const double eps=1e-6;
char s[5];
int a[5];
int dcmp(double a,double b)//判断大小用的,注意double形的相等的判断
{
if(fabs(a-b)<eps)return 0;
if(a<b) return -1;
return 1;
}
double suan(double x,int op,double y)
{
if(!dcmp(x,-INF)||!dcmp(y,-INF)) return -INF;
if(!dcmp(y,0)&&op==3) return -INF;//0为除数,结果为无穷小
if(op==0) return x+y;
if(op==1) return x-y;
if(op==2) return x*y;
if(op==3)return x/y;
return -INF;
}
bool gao(int x,int y,int z)//判断是否可以结果为24
{
double res=0,tmp=0;
//各种加括号形式
//case 1 (((AB)C)D)
res=suan(a[0],x,a[1]);
res=suan(res,y,a[2]);
res=suan(res,z,a[3]);
if(!dcmp(res,24)) return true;
//case 2 ((AB)(CD))
res=suan(a[0],x,a[1]);
tmp=suan(a[2],z,a[3]);
res=suan(res,y,tmp);
if(!dcmp(res,24)) return true;
//case 3 (A(B(CD)))
res=suan(a[2],z,a[3]);
res=suan(a[1],y,res);
res=suan(a[0],x,res);
if(!dcmp(res,24)) return true;
//case 4 ((A(BC))D)
res=suan(a[1],y,a[2]);
res=suan(a[0],x,res);
res=suan(res,z,a[3]);
if(!dcmp(res,24)) return true;
//case 5 (A((BC)D))
res=suan(a[1],y,a[2]);
res=suan(res,z,a[3]);
res=suan(a[0],x,res);
if(!dcmp(res,24)) return true;
return false;
}
bool solve()
{
sort(a,a+4);
do
{
for(int i=0;i<4;i++)
{
for(int j=0;j<4;j++)
{
for(int k=0;k<4;k++)
{
if(gao(i,j,k))
return true;
}
}
}
}while(next_permutation(a,a+4));//生成全排列的函数
return false;
}
int main()
{
int T;
int cas=0;
scanf("%d",&T);
while(T--)
{
cas++;
for(int i=0;i<4;i++)
{
scanf("%s",s);
if(strlen(s)==1)
{
if(s[0]>='0'&&s[0]<='9') a[i]=s[0]-'0';
else if(s[0]=='A')a[i]=1;
else if(s[0]=='J')a[i]=11;
else if(s[0]=='Q')a[i]=12;
else if(s[0]=='K')a[i]=13;
}
else a[i]=10;
}
bool ok=solve();
printf("Case #%d",cas);
if(ok)
printf(": Yes\n");
else
printf(": No\n");
}
return 0;
}