zoukankan      html  css  js  c++  java
  • 牛客-装货物

    题目传送门

    sol:题目的数据范围就是对解决方案的一种提示,原先以为当数据范围只有$20$的时候都是dfs或者二进制枚举这种,从这题了解到还有状压dp。不解释了,反正就是状压dp,做的不多,记录一下。

    • 状压dp
      #include <bits/stdc++.h>
      using namespace std;
      typedef long long LL;
      typedef pair<int, int> PII;
      const int INF = 0x3f3f3f3f;
      const int MAXN = 22;
      int a[MAXN];
      // dp1最小箱子消耗,dp2在最小箱子消耗的前提下最后一个箱子的最大剩余
      int dp1[1 << MAXN | 10], dp2[1 << MAXN | 10];
      int main() {
          int t; scanf("%d", &t);
          while (t--) {
              int n, m, w, _max = 0;
              scanf("%d%d%d", &n, &m, &w);
              for (int i = 0; i < n; i++) { //状压dp下标还是从0开始好了,从1开始写了几次都wa
                  scanf("%d", &a[i]);
                  _max = max(_max, a[i]);
              }
              if (_max > w) {
                  puts("No");
                  continue;
              }
              memset(dp1, INF, sizeof(int) * (1 << n));
              memset(dp2, 0, sizeof(int) * (1 << n));
              dp1[0] = 0;
              for (int i = 0; i < (1 << n); i++) {
                  for (int j = 0; j < n; j++) {
                      int k = 1 << j;
                      if (i & k) continue;
                      if (dp2[i] >= a[j] && (dp1[i] < dp1[i | k] || dp1[i] == dp1[i | k] && dp2[i | k] < dp2[i] - a[j])) {
                          dp1[i | k] = dp1[i];
                          dp2[i | k] = dp2[i] - a[j];
                      } else if (dp1[i] + 1 <= dp1[i | k]) {
                          dp1[i | k] = dp1[i] + 1;
                          dp2[i | k] = w - a[j];
                      }
                  }
              }
      //        printf("%d
      ", dp1[(1 << n) - 1]);
              puts(dp1[(1 << n) - 1] <= m ? "Yes" : "No");
          }
          return 0;
      }
    • 爆搜
      #include <bits/stdc++.h>
      using namespace std;
      typedef long long LL;
      typedef pair<int, int> PII;
      int a[30], c[30];
      int n, m, w;
      bool dfs(int i) {
          if (i > n) return true;
          int k = min(i + 1, m); // 这个优化很关键
          for (int j = 1; j <= k; j++) {
              if (c[j] + a[i] <= w) {
                  c[j] += a[i];
                  if (dfs(i + 1)) return true;
                  c[j] -= a[i];
              }
          }
          return false;
      }
      int main() {
          int t; scanf("%d", &t);
          while (t--) {
              scanf("%d%d%d", &n, &m, &w);
              for (int i = 1; i <= n; i++) scanf("%d", &a[i]);
              sort(a + 1, a + 1 + n, greater<int>());
              if (a[1] > w) {
                  puts("No");
                  continue;
              }
              if (m >= n) {
                  puts("Yes");
                  continue;
              }
              memset(c, 0, sizeof(c));
              puts(dfs(1) ? "Yes" : "No");
          }
          return 0;
      }

      数据比较水,在爆搜优化到极致的情况下能AC,自己写的时候没有那个关键的优化总是超时,还是挺妙的。

  • 相关阅读:
    BOI 2002 双调路径
    BOI'98 DAY 2 TASK 1 CONFERENCE CALL Dijkstra/Dijkstra+priority_queue/SPFA
    USACO 2013 November Contest, Silver Problem 2. Crowded Cows 单调队列
    BOI 2003 Problem. Spaceship
    USACO 2006 November Contest Problem. Road Blocks SPFA
    CEOI 2004 Trial session Problem. Journey DFS
    USACO 2015 January Contest, Silver Problem 2. Cow Routing Dijkstra
    LG P1233 木棍加工 动态规划,Dilworth
    LG P1020 导弹拦截 Dilworth
    USACO 2007 February Contest, Silver Problem 3. Silver Cow Party SPFA
  • 原文地址:https://www.cnblogs.com/Angel-Demon/p/12188015.html
Copyright © 2011-2022 走看看