• topcoder srm 605 div1


    problem1 link

    首先按照type分类,同一类如果都是负数,那么取最大值,否则将所有的正数加起来作为这个type的价值。然后就是二维的背包。

    problem2 link

    从小到大将每个数字分到A或者B集合。设$f[i][j][m]$表示已经分配完前$i$个数字,A集合中分配了$j$个数字,已经分配的前$i$个数字中的最大的$K$个数字(即$[i-K+1,i]$)在两个集合中的分布情况为$m$的划分方案数。$m$是一个$K$位二进制数字。

    problem3 link

    设原来的数组为$P$,最终的数组为$S$.

    有两个重要的性质:(1)$S$中的数字的前后顺序与其在$P$中的前后顺序是一致的,比如$P=[3,2,1,4,5]$不会使得$S=[2,3,1,4,5]$;(2)$S$中不会出现两段相同的数字,比如$S=[3,2,3,4,5]$

    所以只需要挨个确定$S$中的每个数字,并记录$S$中最后确定的数字是$P$中的哪一个即可。

    设$f[i][j][k][t]$表示已经确定好了$S$的前$i$个数字,其中$S[i]=P[j]$.并且已经使用了$k$次操作。$t$是一个tag(可以取0或者1两个值),它表示当用$j$去扩展到$i$时是否使用了一次操作。这个的意义在于如果后面还要用$P[j]$去扩展到$S[i+1]$,如果前面已经使用了一次操作,那么后面的操作数就不用再加1了。

    code for problem1

    #include <limits>
    #include <unordered_map>
    #include <vector>
    
    class AlienAndHamburgers {
     public:
      int getNumber(const std::vector<int> &type, const std::vector<int> &taste) {
        std::unordered_map<int, int> a;
        for (size_t i = 0; i < type.size(); ++i) {
          int t = type[i];
          int c = taste[i];
          if (a.find(t) == a.end()) {
            a[t] = c;
            continue;
          }
          if (c < 0) {
            if (a[t] < 0) {
              a[t] = std::max(a[t], c);
            }
          } else {
            a[t] = std::max(a[t] + c, c);
          }
        }
        int m = static_cast<int>(a.size());
        std::vector<std::vector<int>> f(
            m, std::vector<int>(m + 1, std::numeric_limits<int>::lowest()));
        int idx = 0;
        for (const auto &e : a) {
          int c = e.second;
          if (idx == 0) {
            f[0][0] = 0;
            f[0][1] = c;
            ++idx;
            continue;
          }
          for (int j = 0; j <= idx; ++j) {
            f[idx][j] = std::max(f[idx][j], f[idx - 1][j]);
            f[idx][j + 1] = std::max(f[idx][j + 1], f[idx - 1][j] + c);
          }
          ++idx;
        }
        int result = 0;
        for (int i = 1; i <= idx; ++i) {
          result = std::max(result, i * f[idx - 1][i]);
        }
        return result;
      }
    };

    code for problem2

    #include <cmath>
    #include <vector>
    
    class AlienAndSetDiv1 {
      static constexpr int kMod = 1000000007;
    
     public:
      int getNumber(int N, int K) {
        std::vector<std::vector<std::vector<int>>> f(
            N + N + 1,
            std::vector<std::vector<int>>(N + 1, std::vector<int>(1 << K)));
        if (K >= N + N) {
          return AnySplit(N);
        }
        for (int i = 0; i < (1 << K); ++i) {
          std::vector<int> a, b;
          for (int j = 0; j < K; ++j) {
            if ((i & (1 << j)) == 0) {
              a.push_back(j + 1);
            } else {
              b.push_back(j + 1);
            }
          }
          bool tag = true;
          for (std::size_t j = 0; j < a.size() && j < b.size(); ++j) {
            if (std::abs(a[j] - b[j]) < K) {
              tag = false;
              break;
            }
          }
          if (tag) {
            f[K][a.size()][i] += 1;
          }
        }
    
        std::vector<int> bit_num(1 << K);
        for (int i = 1; i < (1 << K); ++i) {
          bit_num[i] = bit_num[i >> 1] + (i & 1);
        }
        std::vector<std::vector<int>> indices0(1 << K, std::vector<int>(K + 1));
        std::vector<std::vector<int>> indices1(1 << K, std::vector<int>(K + 1));
        for (int i = 0; i < (1 << K); ++i) {
          int num0 = 0;
          int num1 = 0;
          for (int j = 0; j < K; ++j) {
            if ((i & (1 << j)) == 0) {
              ++num0;
              indices0[i][num0] = j;
            } else {
              ++num1;
              indices1[i][num1] = j;
            }
          }
        }
        for (int i = K + 1; i <= N + N; ++i) {
          for (int a = 0; a < i && a <= N; ++a) {
            int b = i - 1 - a;
            for (int k = 0; k < (1 << K); ++k) {
              if (f[i - 1][a][k] != 0) {
                if (a + 1 <= N) {
                  if (a >= b) {
                    (f[i][a + 1][k >> 1] += f[i - 1][a][k]) %= kMod;
                  } else {
                    int t = bit_num[k];
                    if ((t < b - a) || (indices1[k][t - (b - a) + 1] == 0)) {
                      (f[i][a + 1][k >> 1] += f[i - 1][a][k]) %= kMod;
                    }
                  }
                }
                if (b + 1 <= N) {
                  if (a <= b) {
                    (f[i][a][(k >> 1) | (1 << (K - 1))] += f[i - 1][a][k]) %= kMod;
                  } else {
                    int t = K - bit_num[k];
                    if ((t < a - b) || (indices0[k][t - (a - b) + 1] == 0)) {
                      (f[i][a][(k >> 1) | (1 << (K - 1))] += f[i - 1][a][k]) %=
                          kMod;
                    }
                  }
                }
              }
            }
          }
        }
        int result = 0;
        for (int i = 0; i < (1 << K); ++i) {
          (result += f[N + N][N][i]) %= kMod;
        }
        return result;
      }
    
     private:
      int AnySplit(int n) {
        std::vector<std::vector<int>> c(2 * n + 1, std::vector<int>(2 * n + 1, 0));
        c[0][0] = c[1][0] = c[1][1] = 1;
        for (int i = 2; i <= 2 * n; ++i) {
          c[i][0] = c[i][i] = 1;
          for (int j = 1; j < i; ++j) {
            c[i][j] = (c[i - 1][j - 1] + c[i - 1][j]) % kMod;
          }
        }
        return c[n + n][n];
      }
    };

    code for problem3

    #include <vector>
    #include <cstring>
    
    int f[200][200][201][2];
    
    class AlienAndPermutation {
     public:
      int getNumber(const std::vector<int> &P, int K) {
        if (K == 0) {
          return 1;
        }
        int n = static_cast<int>(P.size());
        std::vector<std::vector<bool>> tag(n, std::vector<bool>(n, true));
        for (int i = 0; i < n; ++i) {
          for (int j = 0; j < n; ++j) {
            for (int k = std::min(i, j), stop = std::max(i, j); k <= stop; ++k) {
              if (P[k] > P[i]) {
                tag[i][j] = false;
                break;
              }
            }
          }
        }
        memset(f, -1, sizeof(f));
        return dfs(0, 0, K, 0, n, tag);
      }
    
     private:
      int dfs(int i, int j, int k, int t, int n,
              const std::vector<std::vector<bool>> &tag) {
        constexpr int kMod = 1000000007;
        if (k < 0) {
          return 0;
        }
        if (j == n) {
          return 1;
        }
        if (i == n) {
          return 0;
        }
        int &result = f[i][j][k][t];
        if (result != -1) {
          return result;
        }
        result = dfs(i + 1, j, k, 0, n, tag);
        if (tag[i][j]) {
          int new_k = k - ((i != j && t == 0) ? 1 : 0);
          int new_t = (t != 0 || i != j) ? 1 : 0;
          (result += dfs(i, j + 1, new_k, new_t, n, tag)) %= kMod;
        }
        return result;
      }
    };
  • 相关阅读:
    关于下下载typora的相关说明
    Vue项目vscode 安装eslint插件的方法(代码自动修复)
    [0].Net开发者社区--您好大的官威啊!
    关于hadoop安装后无法访问web界面查看查看 NameNode 和 Datanode 信息
    C#(winform)记录阻止关闭页面方法
    Android开发:记录Cannot resolve symbol'R'问题解决记录
    C#Winform开发杂项记录
    C#Winform 使用NPOI导入、导出Excel
    C#记录一些用到的比对方法
    C#(Winform开发)Excel导出
  • 原文地址:https://www.cnblogs.com/jianglangcaijin/p/9463711.html
Copyright © 2020-2023  润新知