益智游戏
题目链接:SSL 2875
题目大意
给你四个 1~9 的数,问你是否可以通过加减乘除和加括号使得式子等于 24。
四个数都要用,可以调换数的位置。
思路
直接全排列然后 dfs 暴搜即可。
暴搜就是把区间分成两半,继续搜索两边,然后每边可能得出的结果分别进行加减乘除四种操作。
除法的时候要判断是否能整除和除数是否为 0 0 0。
然后最后在所有的答案中看是否有 24 24 24。
然后因为顺序要调换,所以我们要对每个排列都暴搜一遍。
代码
#include<cstdio>
#include<vector>
#include<cstring>
using namespace std;
int n;
int a[5], r[5], xx[5];
vector <int> pl[5][5];
bool in[5][5], read[5];
void dfs(int l, int r) {
//暴搜
in[l][r] = 1;
if (l == r) {
pl[l][r].push_back(a[l]);
return ;
}
for (int i = l; i < r; i++) {
if (!in[l][i]) dfs(l, i);
if (!in[i + 1][r]) dfs(i + 1, r);
for (int j = 0; j < pl[l][i].size(); j++)
for (int k = 0; k < pl[i + 1][r].size(); k++) {
pl[l][r].push_back(pl[l][i][j] + pl[i + 1][r][k]);
pl[l][r].push_back(pl[l][i][j] - pl[i + 1][r][k]);
pl[l][r].push_back(pl[l][i][j] * pl[i + 1][r][k]);
if (pl[i + 1][r][k] != 0 && pl[l][i][j] % pl[i + 1][r][k] == 0)
pl[l][r].push_back(pl[l][i][j] / pl[i + 1][r][k]);
}
}
}
bool dfs_(int now) {
//造全排列
if (now > 4) {
memset(in, 0, sizeof(in));//初始化
for (int i = 1; i <= 4; i++)
for (int j = 1; j <= 4; j++)
pl[i][j].clear();
for (int i = 1; i <= 4; i++)
a[xx[i]] = r[i];
dfs(1, 4);
for (int i = 0; i < pl[1][4].size(); i++)//看有没有式子可以是24
if (pl[1][4][i] == 24) {
printf("1\n");
return 1;
}
return 0;
}
for (int i = 1; i <= 4; i++)
if (!read[i]) {
read[i] = 1;
xx[now] = i;
if (dfs_(now + 1)) return 1;
xx[now] = 0;
read[i] = 0;
}
return 0;
}
void work() {
memset(read, 0, sizeof(read));
if (dfs_(1)) return ;
printf("0\n");
return ;
}
int main() {
// freopen("game.in", "r", stdin);
// freopen("game.out", "w", stdout);
scanf("%d", &n);
while (n--) {
scanf("%d %d %d %d", &r[1], &r[2], &r[3], &r[4]);
work();
}
fclose(stdin);
fclose(stdout);
return 0;
}