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,自己写的时候没有那个关键的优化总是超时,还是挺妙的。

  • 相关阅读:
    form2js的使用(续BootstrapTable)
    input限定文件上传类型:Microsoft Office MIME types
    Zookeeper环境搭建
    Zookeeper一致性协议——ZAB
    Zookeeper简介
    IOC容器加载流程
    Spring Bean 生命周期
    Spring Framework 5 模块组成、体系结构、整体架构
    什么是 IoC?什么是 DI ? 他们之间有什么关系?
    【MySQL实战45讲】索引部分整理
  • 原文地址:https://www.cnblogs.com/Angel-Demon/p/12188015.html
Copyright © 2011-2022 走看看