3 1 2 4 3 9 2 1
0 2 4 5
/* 题意:找出用n个砝码称重不能表示的重量有哪些,从小到大输出。 注意:每种砝码既可以放左盘又可以放右盘,按照左物右码的规则,放在左盘的时候就取减号,放在右盘的时候就取加号。 */ #include <iostream> #include <algorithm> #include <stdio.h> #include <string.h> using namespace std; int c1[10010],c2[10010]; int ans[10010]; int a[111]; int sum; int main() { int n; while(~scanf("%d",&n)) { sum = 0; for(int i = 1; i <= n; i ++) { scanf("%d",&a[i]); sum += a[i]; } memset(c1,0,sizeof(c1)); memset(c2,0,sizeof(c2)); c1[0] = 1;///一定要注意这个初始化,非常有用,而且不会对最终正确的结果产生影响,但是没有它的话会错 for(int i = 1; i <= n; i ++) { for(int j = 0; j <= sum; j ++)///j对应最大的重量 ///(j+k<=sum)表明最大可取的情况不要大于sum,该括号中最大只能表示a[i],不能大于 for(int k = 0; j + k <= sum && k <= a[i]; k += a[i]) { ///两括号中的砝码可能都是放在右边,或者放在两个盘子 ///注意,都放在左盘子的那就不是称重了 ///还有就是要对每种情况取绝对值 if(k >= j) c2[k - j] += c1[j]; else c2[j - k] += c1[j]; c2[k+j] += c1[j]; } for(int j = 0; j <= sum; j ++) { c1[j] = c2[j]; c2[j] = 0; } } memset(ans,0,sizeof(ans)); int s = 0;///统计数量 for(int i = 0; i <= sum; i ++) if(c1[i] == 0) { ans[s] = i; s ++; } printf("%d\n",s); if(s) { printf("%d",ans[0]); for(int i = 1; i < s; i ++) printf(" %d",ans[i]); printf("\n"); } } return 0; }