题意是给你n个砝码问能在一个天平上称多少种重量。
砝码可以放在天平的两边,很容易想到用指数的正负表示放在左边还是右边,但是数组下标不可能是负数,可以用1w表示没有放砝码,比1w多多少就表示右边重多少,比1w少多少就表示左边重多少,然后就简单了。
#include <cstdio> #include <cstring> #include <iostream> #include <algorithm> using namespace std; #define maxn 21111 #define add 10000 long long a[maxn], b[maxn]; int n, num[111]; int c[11], Max; bool vis[maxn/2]; int ans[maxn/2]; int main () { //freopen ("data.txt", "r", stdin); while (cin >> n) { Max = 0; for (int i = 1; i <= n; i++) { cin >> num[i]; Max += num[i]; } memset (a, 0, sizeof a); a[add] = 1, a[add+num[1]] = 1, a[add-num[1]] = 1; for (int i = 2; i <= n; i++) { memset (b, 0, sizeof b); for (int j = 0; j <= Max+add; j++) b[j] = a[j]; for (int j = 0; j+num[i] <= Max+add; j++) b[j+num[i]] += a[j]; for (int j = 0; j <= Max+add; j++) if (j-num[i] >= 0) b[j-num[i]] += a[j]; for (int j = 0; j <= Max+add; j++) a[j] = b[j]; } memset (vis, 0, sizeof (vis)); for (int i = add+1; i <= Max+add; i++) if (a[i]) vis[i-add] = 1; for (int i = add-1; i >= add-Max; i--) if (a[i]) vis[add-i] = 1; int cnt = 0; for (int i = 1; i <= Max; i++) if (!vis[i]) ans[++cnt] = i; cout << cnt << endl; for (int i = 1; i <= cnt-1; i++) cout <<ans[i] << " "; if (cnt) cout << ans[cnt] << endl; } return 0; }