题目描述
给出四个数,判断能否算成24,可以调换顺序,只能加减乘除和括号
样例输入
2
1 2 3 7
1 1 1 1
样例输出
1
0
思路
全排列之后爆搜,然后分组考虑括号的情况
虽然我还是没A
但是是题目的描述有锅,要不然就切了…
代码
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
int b, a[15], ans[4][4][100005], n, num[10][10], rr[12], xx[12], read[12];
int dfs(int l, int r, int x)
{
if(l == r) ans[l][r][++num[l][r]] = rr[l];
if(r - l == 1) {
if(x == 1) ans[l][r][++num[l][r]] = rr[r] + rr[l];
if(x == 2) ans[l][r][++num[l][r]] = rr[l] - rr[r];
if(x == 3) ans[l][r][++num[l][r]] = rr[l] * rr[r];
if(a[r] != 0 && a[l] % a[r] == 0) ans[l][r][++num[l][r]] = rr[l] / rr[r];
}//计算分了之后的小区间
for(int i = l; i <= r; ++i)
{
int sum, sum2;
if(!num[l][i]) for(int j = 1; j <= 5; ++j) dfs(l, i, j);
if(!num[i + 1][r]) for(int k = 1; k <= 5; ++k) dfs(i + 1, r, k);
for(int j = 1; j <= num[l][i]; ++j) {
sum = ans[l][i][j];
for(int k = 1; k <= num[i + 1][r]; ++k) {
sum2 = ans[i + 1][r][k];
if(x == 1) ans[l][r][++num[l][r]] = sum + sum2;
if(x == 2) ans[l][r][++num[l][r]] = sum - sum2;
if(x == 3) ans[l][r][++num[l][r]] = sum * sum2;
if(sum2 != 0 && sum % sum2 == 0) ans[l][r][++num[l][r]] = sum / sum2;
}//分别处理
}
}
}
void dfss(int now)
{
if(now > 3)
{
memset(num, 0, sizeof(num));
memset(ans, 0, sizeof(ans));
for(int i = 0; i <= 3; ++i)
rr[xx[i]] = a[i];
for(int j = 1; j <= 4; ++j)
dfs(0, 3, j);
for(int j = 1; j <= num[0][3]; ++j)
if(ans[0][3][j] == 24) {
printf("1\n");
b = 1;
break;
}
if(b) return;
}
for(int i = 0; i <= 3; ++i)
{
if(!read[i]) {
read[i] = 1;
xx[now] = i;
dfss(now + 1);
if(b) return;
read[i] = 0;
xx[now] = 0;
}
}//求全排列
}
int main()
{
// freopen("game.in", "r", stdin);
// freopen("game.out", "w", stdout);
scanf("%d", &n);
for(int i = 1; i <= n; ++i)
{
b = 0;
memset(num, 0, sizeof(num));
memset(ans, 0, sizeof(ans));
scanf("%d%d%d%d", &a[0], &a[1], &a[2], &a[3]);
dfss(0);
if(!b) printf("0\n");
}
return 0;
fclose(stdin);
fclose(stdout);
}