[关闭]
@guxier 2022-03-30T06:28:59.000000Z 字数 1667 阅读 389

砝码称重

dp


题目描述

你有一架天平和 N 个砝码,这 N 个砝码重量依次是
请你计算一共可以称出多少种不同的正整数重量?
注意砝码可以放在天平两边。

输入格式

输入的第一行包含一个整数 N 。
第二行包含 N 个整数:

输出格式

输出一个整数代表答案。

数据范围

对于的评测用例,
对于所有评测用例,,N 个砝码总重不超过

输入样例:

  1. 3
  2. 1 4 6

输出样例:

  1. 10

样例解释

能称出的 10 种重量是:1、2、3、4、5、6、7、9、10、11 。

  1. 1 = 1
  2. 2 = 6 4 (天平一边放 6,另一边放 4);
  3. 3 = 4 1
  4. 4 = 4
  5. 5 = 6 1
  6. 6 = 6
  7. 7 = 1 + 6
  8. 9 = 4 + 6 1
  9. 10 = 4 + 6
  10. 11 = 1 + 4 + 6

题解

(DP)

y总用了在状态转移方程上用了dp(i) |= dp(i-1)如果i-1个的时候不合法,则i也会不合法,同理i-1合法,或运算会使得dp(i)的结果与i-1相同

  1. #include <bits/stdc++.h>
  2. #define ios ios::sync_with_stdio(false), cin.tie(0)
  3. #define sd(n) scanf("%d" , &n)
  4. #define rep(i, a, n) for ( int i = a; i <= n; i++)
  5. #define per(i, a, n) for ( int i = n; i >= a; i--)
  6. #define debug(x) cout << #x << ": " << x << endl
  7. #define MOD 1000000007
  8. #define INF 0x3f3f3f3f
  9. typedef long long LL;
  10. using namespace std;
  11. const int N =2e5 + 10 , B = 1e5 ;
  12. int n , m , w[150];
  13. int dp[150][N];
  14. int main()
  15. {
  16. sd(n);
  17. rep(i , 1 , n)
  18. {
  19. sd(w[i]);
  20. m += w[i];
  21. }
  22. /** Base偏移量
  23. * 对于前i个砝码,总重量为j的方法集合
  24. * 属性 : 可以称出该种重量重(Bool类型) 0 / 1
  25. * 1、不选j砝码 dp[i][j] = dp[i-1][j];
  26. * 2、j放左边 dp[j][j] += dp[i-1][j - w[i]];
  27. * 3、j放右边 dp[i][j] += dp[i-1][j + w[i]];
  28. **/
  29. dp[0][B] = 1;
  30. rep(i , 1 , n)
  31. rep(j , -m , m)
  32. {
  33. dp[i][j + B] = dp[i-1][j + B];
  34. if(j - w[i] >= -m) dp[i][j + B] += dp[i-1][j - w[i] + B];
  35. if(j + w[i] <= m) dp[i][j + B] += dp[i-1][j + w[i] + B];
  36. }
  37. int ans = 0;
  38. rep(i , 1 , m)
  39. if(dp[n][i + B]) ans ++;
  40. cout << ans;
  41. return 0;
  42. }

(位运算)

不懂bitset可以戳这里

  1. #include <bits/stdc++.h>
  2. #define ios ios::sync_with_stdio(false), cin.tie(0)
  3. #define sd(n) scanf("%d",&n)
  4. #define rep(i, a, n) for (register int i = a; i <= n; i++)
  5. #define per(i, a, n) for (register int i = n; i >= a; i--)
  6. #define debug(x) cout << #x << ": " << x << endl
  7. #define MOD 1000000007
  8. #define INF 0x3f3f3f3f
  9. typedef long long LL;
  10. using namespace std;
  11. const int N =1e5 + 10 ;
  12. int n , w[150];
  13. bitset<N> s;
  14. int main()
  15. {
  16. sd(n);
  17. rep(i , 1 , n) sd(w[i]);
  18. s[0] = 1; //边界
  19. rep(i , 1 , n) s |= s << w[i];
  20. rep(i , 1 , n) s |= s >> w[i];
  21. cout << s.count() -1; //有多少个1,除去重量位0的边界
  22. cout << endl;
  23. return 0;
  24. }

运行时间对比图如下:

AC_FaMa.jpg

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注