0 题目来源

第十二届蓝桥杯省赛A组赛题

1 涉及到的知识点

动态规划

2 题目

image.png
image.png

3 思路

经过分析本题可以看出,放入秤上下一个砝码后,能够称出的重量数目,取决于放入上一个砝码后,能够称出的重量数目,即下一个状态取决于上一个状态,这是很明显的动态规划思想。
另外,假设现在天平可以称出重量A,则放入砝码C后,能得到的重量为A+C、|A-C|、C三种情况
因此,我们维护一个集合vec——存放天平当前能够称出的重量(不重复、不存零)。
在每次放入砝码C后,就遍历该集合vec,计算vec[i]+C、|vec[i]-c|,把计算结果以及砝码本身C加入到集合中(需要判断是否重复,若集合中已有,则不加入)
由于在遍历集合vec的过程中,是不需要遍历我们新加入的元素的(加入的砝码只与原来的重量进行运算),因此我们使用一个临时集合对新加入的元素进行存储,待遍历完成后,统一将新加入的元素加入到总集合vec中。

本思路没有采用传统的dp数组思路,之后有空会补充dp数组相关的思路。

4 代码

  1. #include<iostream>
  2. #include<vector>
  3. #include<cmath>
  4. using namespace std;
  5. int mp[100001];
  6. vector<int> mainvector;
  7. int main()
  8. {
  9. int n;
  10. cin >> n;
  11. for (int i = 0; i < n; i++)
  12. {
  13. int temp;
  14. cin >> temp;
  15. vector<int> vec;
  16. for (int j = 0; j < mainvector.size(); j++)
  17. {
  18. if (!mp[temp + mainvector[j]])
  19. {
  20. mp[temp + mainvector[j]] = 1;
  21. vec.push_back(temp + mainvector[j]);
  22. }
  23. if (!mp[abs(temp - mainvector[j])])
  24. {
  25. mp[abs(temp - mainvector[j])] = 1;
  26. vec.push_back(abs(temp - mainvector[j]));
  27. }
  28. }
  29. for (int j = 0; j < vec.size(); j++)
  30. {
  31. if(vec[j] != 0)
  32. mainvector.push_back(vec[j]);
  33. }
  34. if (!mp[temp] && temp != 0)
  35. {
  36. mp[temp] = 1;
  37. mainvector.push_back(temp);
  38. }
  39. }
  40. cout << mainvector.size();
  41. return 0;
  42. }