Codeforces 626F Group Projects (DP)

题目链接 F.Group Projects

题意 把 \(n\) 个物品分成若干组,每个组的代价为组内价值的极差,求所有组的代价之和不超过 \(k\) 的方案数。

考虑 DP, \(f[i][j][k]\) 表示考虑到第 \(i\) 个物品的时候,还有 \(j\) 组尚未分配完毕,当前状态总代价为 \(k\) 的方案数
先把 \(a[]\) 升序排列,那么极差就可以转化为后面元素减前面的元素不听叠加的效果。
当考虑第 \(i\) 个物品的时候有 \(4\) 种转移方法 :

  • 当前物品新开一组并且等待分配
  • 当前物品新开一组并且这个物品单独当做一组
  • 当前物品插入到之前的 \(j\) 组中的一组,并让这个组继续等待分配,那么有 \(j\) 种插入的方案
  • 当前物品插入到之前的 \(j\) 组中的一组,并作为这个组的最大值(停止分配),同样有 \(j\) 种插入的方案
    时间复杂度 \(O(n^2k)\)
view code
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>

#define LL long long
#define rep(i, a, b) for(int i(a); i <= b; ++ i) 
#define dec(i, a, b) for(int i(a); i >= b; -- i) 
//mt19937 mrand(random_device{}()); 
//int rnd(int x) { return mrand() % x;}
template <typename T> void chkmax(T &x, T y) { x = x >= y ? x : y; }
template <typename T> void chkmin(T &x, T y) { x = x <= y ? x : y; }
template <typename T> T abs(T x) {return x >= 0 ? x : -x;}

const int N = 202, M = 1010, MOD = 1e9 + 7;

int n, m;
int a[N];
LL f[2][N][M];
LL ans;

void add(LL &x, LL y) {
  x += y; 
  while(x >= MOD) {
    x -= MOD;
  }
}

int main() {

  scanf("%d%d", &n, &m);
  rep(i, 1, n) {
    scanf("%d", a + i);
  }

  std::sort(a + 1, a + 1 + n);

  f[0][0][0] = 1;
  //f[i][j][k] 表示 在前 i 个物品中选, 且剩余 j 个背包没有填完  并且 不平衡值 为 k
  rep(i, 0, n - 1) {
    std::memset(f[i + 1 & 1], 0, sizeof f[i + 1 & 1]);
    rep(j, 0, n) {
      rep(k, 0, m) { if(f[i & 1][j][k] &&  k + j * (a[i + 1] - a[i]) <= m) {
          
          int cnt = k + j * (a[i + 1] - a[i]);
          add(f[i + 1 & 1][j + 1][cnt], f[i & 1][j][k]); //新开一个背包 并且这个背包没有填完
          add(f[i + 1 & 1][j][cnt], f[i & 1][j][k]); //新开一个背包 并且这个背包填完了
          //放入之前的背包
          if(j) {
            add(f[i + 1 & 1][j][cnt], f[i & 1][j][k] * j % MOD); //没有填完任何一个背包
            add(f[i + 1 & 1][j - 1][cnt], f[i & 1][j][k] * j % MOD); //填完一个背包
          }
        }
      }
    }
  }
  
  rep(i, 0, m) add(ans, f[n & 1][0][i]);
  printf("%lld", ans);
  return 0;
}

转载于此处

posted @ 2022-03-01 20:46  ccz9729  阅读(46)  评论(0编辑  收藏  举报