PKU/HDU Sum It Up
题目传送门:http://poj.org/problem?id=1564
http://acm.hdu.edu.cn/showproblem.php?pid=1258
解法:深搜+判重
n<=12直接深搜也不会超时,而且数据较弱。题目意思说每个加法中的数字可以出现的次数不能多于原来list里面的数字。但是可能出现一样的加法式子。
比如样例中的4 6 4 3 2 2 1 1,如果直接深搜就会出现两个3+1和两个2+1+1,所以加一个判断重复就可以了。类似的搜索还可以采用状态压缩的解法,效率更快。
#include <iostream> #include <cstdio> #include <cstdlib> #include <ctime> #include <map> #include <cstring> #include <string.h> #include <fstream> #include <vector> #include <cmath> #include <algorithm> using namespace std; int a[15], tot, n; bool flag; int get_sum(int j){ int l = n, tot = 0; while (j > 0){ if (j % 2) tot += a[l]; j /= 2; l--; } return tot; } int d[1<<12], k; void out_put(int x){ int c[15], k = n; while (k >= 1){ c[k--] = x % 2; x /= 2; } bool temp = false; for (int i = 1; i <= n; i++) if (c[i]){ if (temp)printf("+"); else temp = true; printf("%d", a[i]); } printf("\n"); return; } bool is_same(int i, int j){ vector<int> u, v; int l = n; while (i > 0){ if (i % 2) u.push_back(a[l]); i /= 2; l--; } l = n; while (j > 0){ if (j % 2) v.push_back(a[l]); j /= 2; l--; } if (u.size() != v.size())return false; for (l = 0; l < u.size(); l++) if (u[l] != v[l])return false; return true; } void dfs(int s, int i){ if (i == n+1){ s /= 2; if (get_sum(s) == tot){ //判重 int x = 0, j; for (j = 0; j < k; j++) if (is_same(s, d[j])){ x = 1; break; } if (!x){ flag = false; d[k++] = s; } } return; } int t = s * 2; dfs(t + 0, i + 1); dfs(t + 1, i + 1); return; } int main(){ int i; while (scanf("%d%d", &tot, &n) != EOF) { if (!n)break; for (i = 1; i <= n; i++) scanf("%d", &a[i]); printf("Sums of %d:\n", tot); k = 0; flag = true; dfs(0, 0); for (i = k-1; i >= 0; i--) out_put(d[i]); if (flag)printf("NONE\n"); } return 0; }