洛谷 P4095 HEOI2013 Eden 的新背包问题

url: https://www.luogu.com.cn/problem/P4095

tag:
动态规划,背包DP,进制,枚举

思路:
多重背包问题为基础,做两次01背包,前一次后一次,之后对于每次询问的id就跳过那个id求可能的最大值。

代码:

  1. #include <iostream>
  2. #include <cstdio>
  3. #include <cstring>
  4. #include <algorithm>
  5. using namespace std;
  6. typedef long long LL;
  7. const int N = 100010;
  8. struct node{
  9. int id;LL s;
  10. }w[N], v[N];
  11. LL f1[N][1010], f2[N][1010];
  12. int idx, m, n;
  13. int main()
  14. {
  15. cin >> n;
  16. for (int i = 1; i <= n; i++)
  17. {
  18. int cw, cv, c;
  19. cin >> cw >> cv >> c;
  20. int now = 1;
  21. while (now <= c)
  22. {
  23. w[++idx].s = cw * now, v[idx].s = cv * now;
  24. w[idx].id = i, v[idx].id = i;
  25. c -= now, now *= 2;
  26. }
  27. if(c) {
  28. w[++idx].s = cw * c, v[idx].s = cv * c;
  29. w[idx].id = i, v[idx].id = i;
  30. }
  31. }
  32. cin >> m;
  33. n = idx;
  34. for (int i = 1; i <= n; i ++)
  35. {
  36. for (int j = 0; j <= 1000; j ++) f1[i][j] = f1[i - 1][j];
  37. for (int j = 1000; j >= w[i].s; j --)
  38. {
  39. f1[i][j] = max(f1[i][j], f1[i - 1][j - w[i].s] + v[i].s);
  40. }
  41. }
  42. for (int i = n; i >= 1; i --)
  43. {
  44. for (int j = 0; j <= 1000; j ++) f2[i][j] = f2[i + 1][j];
  45. for (int j = 1000; j >= w[i].s; j --)
  46. {
  47. f2[i][j] = max(f2[i][j], f2[i + 1][j - w[i].s] + v[i].s);
  48. }
  49. }
  50. for (int k = 1; k <= m; k ++)
  51. {
  52. int cn, V;
  53. cin >> cn >> V;
  54. cn ++;
  55. LL ans = 0;
  56. int l = 0, r = 0;
  57. while (w[l + 1].id < cn && l < n) ++ l;
  58. r = l;
  59. while (w[r + 1].id <= cn && r < n) ++ r;
  60. for (int j = 0; j <= V; j++)
  61. {
  62. ans = max(ans, f1[l][j] + f2[r + 1][V - j]);
  63. }
  64. cout << ans << endl;
  65. }
  66. return 0;
  67. }
添加新评论