提示:24点
小Hi:小Ho,你仔细观察我们计算24点的方法,来总结有几种情况。
假设我们用⊙表示运算,⊙除了可以表示基本的"+","-","*","/"外。我们还引入两个新的运算,"反-",和"反/"。
比如(a 反/ b)的意思是(b / a)。则对形如(c / (a + b))的形式,就可以等价的描述为((a + b) 反/ c)。
利用这6种运算,可以将所有可能的计算过程归结为2类:
(((a ⊙ b) ⊙ c ) ⊙ d) ((a ⊙ b) ⊙ (c ⊙ d))
小Ho:恩..(小Ho思考了一下)..好像确实是这样。
小Hi:既然我们已经找到了固定的模式,那么剩下的就比较简单了。
将4张牌的值,分别代入a,b,c,d,再把可能的运算符也代入。就可以得到相应的计算式子,将其计算出来,再检查结果是否等于24。
那么小Ho,你觉得有多少种情况呢?
小Ho:由于我们有4个数,所以对于a,b,c,d的对应关系有4!=24种情况。3个运算符,每个运算符可能有6种情况,那就是6^3=216。再考虑到2种不同的模式,所以一共有2 * 24 * 216 = 10368种情况。
小Hi:你的计算中并没有考虑等价的情况,比如a + b 和 b + a,所以实际的情况数其实是小于10368种的。
不过由于对计算机而言,10368种情况数本来也不是很多,而要考虑等价反而显得比较麻烦。所以我们可以不要去考虑加法和乘法的可逆性,直接枚举所有的情况。
#include<stdio.h>
#include<iostream>
#include<string.h>
using namespace std;
int t;
bool used[4];
double nownumber[4],number[4];
char optype[]={'+','-','*','/','@','#'},ops[3];
double calc(double a, double b, char c){
double s = 0.0;
switch (c)
{
case '+': s = a + b;break;
case '-': s = a - b;break;
case '*': s = a*b;break;
case '/': if (b != 0) s = a / b;break;
case '#': if(a!=0)s=b/a;break;
case '@': s=b-a;break;
default: break;
}
return s;
}
bool makeoperation(int depth)
{
if(depth>=3)
{
if(calc(calc(nownumber[0], nownumber[1],ops[0]), calc(nownumber[2], nownumber[3],ops[1]),ops[2]) == 24)
return true;
else if(calc(nownumber[0], calc(nownumber[1], calc(nownumber[2], nownumber[3], ops[2]), ops[1]), ops[0]) == 24 )
return true;
else return false;
}
for(int i=0;i<6;i++)
{
ops[depth]=optype[i];
if(makeoperation(depth+1))
return true;
}
return false;
}
bool makenumber(int depth)
{
if(depth>=4)
return makeoperation(0);
for(int i=0;i<4;i++)
{
if(!used[i])
{
nownumber[depth]=number[i];
used[i]=true;
if(makenumber(depth+1))
return true;
used[i]=false;
}
}
return false;
}
int main()
{
scanf("%d",&t);
while(t--)
{
for(int i=0;i<4;i++)
scanf("%lf",&number[i]);
memset(used,false,sizeof(used));
if (makenumber(0))
cout << "Yes" << endl;
else
cout << "No" << endl;
}
}
大神的解法:
next_permutation(a,a+4); 递增
prev_permutation(a,a+4); 递减
#include<stdio.h>
#include<iostream>
#include<algorithm>
using namespace std;
double a[4];
bool flag;
double so(double a,double b,int k)
{
double s=0.0;
switch(k)
{
case 0:s=a+b;break;
case 1:s=a-b;break;
case 2:s=a*b;break;
case 3:if(b!=0)s=a/b;break;
case 4:s=b-a;break;
case 5:if(a!=0)s=b/a;break;
}
return s;
}
bool pan(int i,int j,int k)
{
if(so(so(so(a[0],a[1],i),a[2],j),a[3],k)==24)return true;
if(so(so(a[0],a[1],i),so(a[2],a[3],k),j)==24)return true;
return false;
}
void solve()
{
for(int i=0; i<6; i++)
for(int j=0; j<6; j++)
for(int k=0; k<6; k++)
if(pan(i,j,k))
{
flag=true;
return;
}
}
int main()
{
int N;
cin>>N;
while(N--)
{
flag=false;
for(int i=0; i<4; i++)
cin>>a[i];
sort(a,a+4);
do
{
solve();
if(flag)break;
}
while(next_permutation(a,a+4));
if(flag)printf("Yes\n");
else printf("No\n");
}
return 0;
}