每日一题——砝码称重

190 阅读2分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 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;\
}