题目意思: 给定n个数和一个目标数,问我们能否找到一个表达式使得这n个数算出来最后的结果等于这个目标值,注意这里的所有运算的优先级一样,都是从左向右的。
解题思路: 1:思路:DFS+状态判重
2:由于这一题的时间给了20s,那么DFS是没问题的。我们只要从第一个开始进行DFS,然后每一次当前是否满足一下条件:1 当前和-32000<=sum<=32000 2当前的状态vis[i][sum]没有出现过 (当使用“/”时候还有判断 是否当前sum%num[i] =0,这里的除号比较不一样)
3:这种题目一般用搜索来做,但是要注意状态的判重,像这一题由于到达num[i]的时候可能求出来的sum不同,所以开个二维vis数组来保存当前状态。路径保存用path数组来记录
代码:
#include <algorithm> #include <iostream> #include <cstring> #include <string> #include <vector> #include <cstdio> #include <stack> #include <queue> #include <set> using namespace std; #define MAXN 110 http:// int t, p, target, flag; int num[MAXN], path[MAXN], ans[MAXN]; int vis[MAXN][100000]; int judge(int m , int pos){ if(m >= -32000 && m <= 32000 && !vis[pos][m]) return 1; return 0; } void DFS(int sum, int pos) { if (pos >= p) { if (sum == target && !flag) {//保存一次即可 memcpy(ans, path, sizeof (ans)); flag = 1; } return; } //四种运算 if (!flag) {//‘+’ if(judge(sum+num[pos] , pos)){ vis[pos][sum+num[pos]] = 1; path[pos-1] = 1 ; DFS(sum+num[pos] , pos+1); } } if (!flag) {//‘-’ if(judge(sum-num[pos] , pos)){ vis[pos][sum-num[pos]] = 1; path[pos-1] = 2 ; DFS(sum - num[pos], pos + 1); } } if (!flag) {//‘*’ if(judge(sum*num[pos] , pos)){ vis[pos][sum*num[pos]] = 1; path[pos-1] = 3 ; DFS(sum*num[pos] , pos+1); } } if (sum % num[pos] == 0 && !flag){//‘/’ if(judge(sum/num[pos] , pos)){ vis[pos][sum/num[pos]] = 1; path[pos-1] = 4 ; DFS(sum / num[pos] , pos+1); } } } void output() { for (int i = 0; i < p; i++) { printf("%d", num[i]); if (ans[i] == 1) printf("+"); if (ans[i] == 2) printf("-"); if (ans[i] == 3) printf("*"); if (ans[i] == 4) printf("/"); } printf("=%d\n", target); } int main() { //freopen("input.txt" , "r" , stdin); scanf("%d%*c", &t); while (t--) { scanf("%d", &p); for (int i = 0; i < p; i++) scanf("%d", &num[i]); scanf("%d", &target); memset(path, 0, sizeof (path)); memset(vis, 0, sizeof(vis)); flag = 0 ; vis[0][num[0]] = 1; DFS(num[0], 1); if (flag) output(); else printf("NO EXPRESSION\n"); } return 0; }