Dang_Quan_10_Tin

KNAPSACK

Mar 16th, 2022 (edited)
528
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 4.00 KB | None | 0 0
  1. #define task "KNAPSACK"
  2. #include <iostream>
  3. #include <cstdio>
  4. #include <vector>
  5. #include <algorithm>
  6.  
  7. using namespace std;
  8.  
  9. using ll = long long;
  10. using ld = long double;
  11.  
  12. constexpr int N = 1e3 + 5;
  13. constexpr ll Inf = 1e17;
  14. int n;
  15. ll dp[N][N * 5];
  16. ll w[N], W, v[N];
  17. pair<ll, ll> f[N * N];
  18.  
  19. void Read()
  20. {
  21.     cin >> n >> W;
  22.  
  23.     for (int i = 1; i <= n; ++i)
  24.         cin >> w[i] >> v[i];
  25. }
  26.  
  27. void Trace_1(int n, int k)
  28. {
  29.     if (n == 0)
  30.         return;
  31.  
  32.     if (dp[n][k] == dp[n - 1][k])
  33.         Trace_1(n - 1, k);
  34.     else
  35.     {
  36.         Trace_1(n - 1, k - w[n]);
  37.         cout << n << " ";
  38.     }
  39. }
  40.  
  41. void Sub_1()
  42. {
  43.     fill_n(&dp[0][0], N * N * 5, -Inf);
  44.  
  45.     dp[0][0] = 0;
  46.  
  47.     for (int i = 1, sum = w[1]; i <= n; sum += w[++i])
  48.     {
  49.         sum = min(sum, (int)W);
  50.         for (int j = 0; j <= sum; ++j)
  51.         {
  52.             dp[i][j] = max(dp[i][j], dp[i - 1][j]);
  53.             if (j >= w[i])
  54.                 dp[i][j] = max(dp[i][j], dp[i - 1][j - w[i]] + v[i]);
  55.         }
  56.     }
  57.  
  58.     pair<ll, int> ans({-Inf, 0});
  59.  
  60.     for (int i = 0; i <= W; ++i)
  61.         ans = max(ans, make_pair(dp[n][i], i));
  62.  
  63.     cout << ans.first << "\n";
  64.  
  65.     Trace_1(n, ans.second);
  66. }
  67.  
  68. #define bit(i, x) (((x) >> (i)) & 1)
  69.  
  70. void Sub_2()
  71. {
  72.  
  73.     int m = n / 2;
  74.     int p = n - m;
  75.  
  76.     struct Val
  77.     {
  78.         ll w, v, mask;
  79.  
  80.         Val(ll w = 0, ll v = 0, ll mask = 0) : w(w), v(v), mask(mask) {}
  81.  
  82.         bool operator<(const Val &a) const
  83.         {
  84.             return w < a.w;
  85.         }
  86.     };
  87.     vector<Val> s;
  88.  
  89.     {
  90.         for (int i = 0; i < (1 << p); ++i)
  91.         {
  92.             ll tmpw(0), tmpv(0);
  93.             for (int j = 0; j < p; ++j)
  94.                 if (bit(j, i))
  95.                 {
  96.                     tmpw += w[j + m + 1];
  97.                     tmpv += v[j + m + 1];
  98.                 }
  99.             if (tmpw <= W)
  100.                 s.emplace_back(tmpw, tmpv, i);
  101.         }
  102.  
  103.         sort(s.begin(), s.end());
  104.  
  105.         f[0].first = -Inf;
  106.         for (int i = 0; i < (int)s.size(); ++i)
  107.             f[i + 1] = max(f[i], make_pair(s[i].v, s[i].mask));
  108.     }
  109.  
  110.     pair<ll, ll> ans({-Inf, 0});
  111.  
  112.     for (int i = 0; i < (1 << m); ++i)
  113.     {
  114.         ll tmpw(0), tmpv(0);
  115.         for (int j = 0; j < m; ++j)
  116.             if (bit(j, i))
  117.             {
  118.                 tmpw += w[j + 1];
  119.                 tmpv += v[j + 1];
  120.             }
  121.  
  122.         if (tmpw <= W)
  123.         {
  124.             tmpw = W - tmpw;
  125.  
  126.             int l = 0, mid, h = s.size() - 1;
  127.  
  128.             while (l <= h)
  129.             {
  130.                 mid = (l + h) / 2;
  131.                 if (s[mid].w <= tmpw)
  132.                     l = mid + 1;
  133.                 else
  134.                     h = mid - 1;
  135.             }
  136.  
  137.             ans = max(ans, make_pair(tmpv + f[l].first, i | (f[l].second << m)));
  138.         }
  139.     }
  140.  
  141.     cout << ans.first << "\n";
  142.  
  143.     for (int i = 0; i < n; ++i)
  144.         if (bit(i, ans.second))
  145.             cout << i + 1 << " ";
  146. }
  147.  
  148. void Trace_3(int n, int k)
  149. {
  150.     if (n == 0)
  151.         return;
  152.  
  153.     if (dp[n][k] == dp[n - 1][k])
  154.         Trace_3(n - 1, k);
  155.     else
  156.     {
  157.         Trace_3(n - 1, k - v[n]);
  158.         cout << n << " ";
  159.     }
  160. }
  161.  
  162. void Sub_3()
  163. {
  164.     fill_n(&dp[0][0], N * N * 5, Inf);
  165.  
  166.     dp[0][0] = 0;
  167.  
  168.     for (int i = 1, sum = v[1]; i <= n; sum += v[++i])
  169.         for (int j = 0; j <= sum; ++j)
  170.         {
  171.             dp[i][j] = min(dp[i][j], dp[i - 1][j]);
  172.             if (j >= v[i])
  173.                 dp[i][j] = min(dp[i][j], dp[i - 1][j - v[i]] + w[i]);
  174.         }
  175.  
  176.     for (int i = 5000; i; --i)
  177.         if (dp[n][i] <= W)
  178.         {
  179.             cout << i << "\n";
  180.             Trace_3(n, i);
  181.             return;
  182.         }
  183. }
  184.  
  185. int32_t main()
  186. {
  187.     ios_base::sync_with_stdio(0);
  188.     cin.tie(0);
  189.     cout.tie(0);
  190.  
  191.     if (fopen(task ".INP", "r"))
  192.     {
  193.         freopen(task ".INP", "r", stdin);
  194.         freopen(task ".OUT", "w", stdout);
  195.     }
  196.  
  197.     Read();
  198.     if (W <= 5000)
  199.         Sub_1();
  200.     else if (n <= 40)
  201.         Sub_2();
  202.     else
  203.         Sub_3();
  204. }
Add Comment
Please, Sign In to add comment