一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第4天,点击查看活动详情。
题目描述
你有一架天平和 N 个砝码,这 N 个砝码重量依次是 W_1, W_2, · · · , W_N。
请你计算一共可以称出多少种不同的重量? 注意砝码可以放在天平两边。
输入格式
输入的第一行包含一个整数 N。
第二行包含 N 个整数:W_1, W_2, W_3, · · · , W_N。
输出格式
输出一个整数代表答案。
样例输入
- 3
- 1 4 6 样例输出
10 样例说明
能称出的 10种重量是:1、2、3、4、5、6、7、9、10、11。
1 = 1;;
2 = 6 − 4 (2=6−4(天平一边放 66,另一边放 4);4);
3 = 4 − 1;
4 = 4;
5 = 6 − 1;
6 = 6;
7 = 1 + 6;
9 = 4 + 6 − 1;
10 = 4 + 6; 11 = 1 + 4 + 6。
评测用例规模与约定
对于 50%的评测用例,1 ≤ N ≤ 15。
对于所有评测用例,1 ≤ N ≤ 100,N,N个砝码总重不超过 100000。
运行限制 最大运行时间:1s
·
·
最大运行内存: 256M
思路****
对于本题可以用多种解法:完全背包问题dp解法、bfs深度优先遍历解法、使用set解法。这里我们使用set解法,刚开始把0加入集合中,然后循环全部的砝码,每一次取数组中的一个砝码挨个与set集合中的数字做加法和减法,把所得结果加入集合中。最后set集合中的元素个数就是我们的答案。 举例:
以1、4、6三个砝码重量为例 set集合元素变化如下: 初始化set {0} 放入1 {1,0} 放入4 {5,3,4,1,0} 放入6 {11,1,9,3,10,2,7,5,4,6,0} 去除0 {11,1,9,3,10,2,7,5,4,6}
#include <cstring>\
#include <algorithm>\
#include <set>\
using namespace std;\
\
const int N = 100000;\
int q[N];\
set<int> ss;\
\
int main()\
{\
int n;\
cin >> n;\
\
for(int i = 0;i < n;i ++)\
{\
cin >> q[i];\
}\
ss.insert(0);\
for(int i = 0;i < n;i ++)\
{\
// 复制一个set集合\
set<int> s = ss;\
for(int aa : s)\
{\
ss.insert(aa + q[i]);// 加上砝码的重量\
ss.insert(abs(aa - q[i]));// 减去该砝码的重量\
}\
}\
\
ss.erase(0);\
cout << ss.size() << endl;\
\
return 0;\
}