题意:给出p个数字,使用+,-,*,/,这四个运算符使得最后结果等于n(四个运算符的优先级相同)
思路:回溯+剪枝,不剪枝的话会TLE。用一个标记数组记录在计算的结果。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;
const int MAXN = 32000;
const int N = 105;
int arr[N], vis[N][MAXN * 2 + 5];
int n, m, flag;
char path[N];
bool judge(int cur, int sum) {
return abs(sum) <= MAXN && !vis[cur][sum + MAXN];
}
void dfs(int cur, int sum) {
if (flag)
return;
if (cur == n) {
if (sum == m)
flag = 1;
return;
}
for (int i = 0; i < 4; i++) {
if (i == 0 && judge(cur, sum + arr[cur])) {
vis[cur][sum + arr[cur] + MAXN] = 1;
path[cur] = '+';
dfs(cur + 1, sum + arr[cur]);
}
if (i == 1 && judge(cur, sum - arr[cur])) {
vis[cur][sum - arr[cur] + MAXN] = 1;
path[cur] = '-';
dfs(cur + 1, sum - arr[cur]);
}
if (i == 2 && judge(cur, sum * arr[cur])) {
vis[cur][sum * arr[cur] + MAXN] = 1;
path[cur] = '*';
dfs(cur + 1, sum * arr[cur]);
}
if (i == 3 && arr[cur] != 0 && judge(cur, sum / arr[cur])) {
vis[cur][sum / arr[cur] + MAXN] = 1;
path[cur] = '/';
dfs(cur + 1, sum / arr[cur]);
}
if (flag)
return;
}
}
void outPut() {
for (int i = 0; i < n; i++) {
if (i)
printf("%c%d", path[i], arr[i]);
else
printf("%d", arr[i]);
}
printf("=%d\n", m);
}
int main() {
int cas;
scanf("%d", &cas);
while (cas--) {
scanf("%d", &n);
for (int i = 0; i < n; i++)
scanf("%d", &arr[i]);
scanf("%d", &m);
memset(vis, 0, sizeof(vis));
vis[0][arr[0] + MAXN] = 1;
flag = 0;
dfs(1, arr[0]);
if (flag)
outPut();
else
printf("NO EXPRESSION\n");
}
return 0;
}