题意: 算24点相信绝大多数人都玩过。就是随机给你四张牌,包括A(1),2,3,4,5,6,7,8,9,10,J(11),Q(12),K(13)。要求只用'+','-','*','/'运算符以及括号改变运算顺序,使得最终运算结果为24(每个数必须且仅能用一次)。游戏很简单,但遇到无解的情况往往让人很郁闷。你的任务就是针对每一组随机产生的四张牌,判断是否有解。我们另外规定,整个计算过程中都不能出现小数
e鸣杯碰到过这道题,当时手算没算出来现在算报了一箭之仇了吧蛤蛤。但是不一样的是这道题运算过程中不会出现小数,有一个坑是当输入是10的时候其实我只读了1,这也是一开始老wa的原因。
这道题直接暴力有点不和谐,所以可以用next_permutation()来做,总结一下,其实所有运算都可以归结为两类,一类是((a@b)@c)@d 另一类是 (a@b)@(c@d)因为只有四个数,所以这么做没问题,但当操作数增多的时候就有点麻烦了,这时候可以考虑递归来做
代码如下:
#include<cstdio>
#include<cstring>
#include<cmath>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#include<vector>
#include<map>
#include<queue>
#include<stack>
#include<string>
#include<map>
#include<set>
using namespace std;
#define LL long long
const int INF = 100000000;
int a[6];
int sol_input(char ch) {
if(ch == 'A') return 1;
else if(ch == 'J') return 11;
else if(ch == 'Q') return 12;
else if(ch == 'K') return 13;
else if(ch == '1') return 10;
else return ch - '0';
}
int oper(int i, int m, int n) { //枚举四种运算符
if(i == 1) return m + n;
if(i == 2) return m - n;
if(i == 3) return m * n;
if(n == 0 || m % n != 0) return INF;
else return m / n;
}
bool calcu1(int i, int j, int k) { //计算顺序1 ((a@b)@c)@d
int tmp1 = oper(i, a[0], a[1]);
int tmp2 = oper(j, tmp1, a[2]);
int tmp3 = oper(k, tmp2, a[3]);
if(tmp3 == 24 || tmp3 == -24) return true;
return false;
}
bool calcu2(int i, int j, int k) { //计算顺序2 (a@b)@(c@d)
int tmp1 = oper(i, a[0], a[1]);
int tmp2 = oper(k, a[2], a[3]);
int tmp3 = oper(j, tmp1, tmp2);
if(tmp3 == 24 || tmp3 == -24) return true;
return false;
}
int main() {
char s[2];
while(scanf("%s", s) != EOF) {
a[0] = sol_input(s[0]);
for(int i = 1; i <= 3; i++) {
scanf("%s", s);
a[i] = sol_input(s[0]);
}
int flag = 0;
sort(a, a+4);
do {
for(int i = 1; i <= 4; i++)
for(int j = 1; j <= 4; j++)
for(int k = 1; k <= 4; k++) {
if(calcu1(i, j, k) || calcu2(i, j, k)) flag = 1;
}
} while(next_permutation(a, a+4) && !flag);
if(flag) printf("Yes\n");
else printf("No\n");
}
return 0;
}