E16 背包DP 分组背包

E16 背包DP 分组背包_哔哩哔哩_bilibili

 

P1757 通天之分组背包 - 洛谷

物品分为 k 组,每组内的物品相互冲突。
已知物品件数和背包容积,每件物品的体积,价值,所属组数。求最大价值。

分组记录物品个数、体积、价值。
依次枚举分组、体积、组内物品,类似 01 背包转移。

// 分组背包 O(nm)
#include<bits/stdc++.h>
using namespace std;

const int N=1010;
int n,m,cnt;
int v[N][N],w[N][N],s[N]; //v[i,j]:第i组第j个物品的体积 s[i]:第i组物品的个数
int f[N][N]; //f[i,j]:前i组物品,能放入容量为j的背包的最大价值

int main(){
  cin>>m>>n; //容积 物品
  for(int i=1,a,b,c;i<=n;i++){
    cin>>a>>b>>c; //体积 价值 所属分组
    v[c][++s[c]]=a;
    w[c][s[c]]=b;
    cnt=max(cnt,c);
  }
  
  for(int i=1;i<=cnt;i++){      //分组
    for(int j=m;j>=0;j--){      //体积
      for(int k=0;k<=s[i];k++){ //组内物品
        if(j>=v[i][k]) f[i][j]=max(f[i][j],f[i-1][j-v[i][k]]+w[i][k]);
        else f[i][j]=max(f[i-1][j],f[i][j]);
      }
    }
  }

  cout<<f[cnt][m];
}

 

// 分组背包+优化空间 O(nm)
#include<bits/stdc++.h>
using namespace std;

const int N=1010;
int n,m,cnt;
int v[N][N],w[N][N],s[N]; //v[i,j]:第i组第j个物品的体积 s[i]:第i组物品的个数
int f[N]; //f[i,j]:前i组物品,能放入容量为j的背包的最大价值

int main(){
  cin>>m>>n; //容积 物品
  for(int i=1,a,b,c;i<=n;i++){
    cin>>a>>b>>c; //体积 价值 所属分组
    v[c][++s[c]]=a;
    w[c][s[c]]=b;
    cnt=max(cnt,c);
  }
  
  for(int i=1;i<=cnt;i++){      //分组
    for(int j=m;j>=0;j--){      //体积
      for(int k=0;k<=s[i];k++){ //组内个数
        if(j>=v[i][k]) f[j]=max(f[j],f[j-v[i][k]]+w[i][k]);
      }
    }
  }

  cout<<f[m];
}

 

P1064 [NOIP 2006 提高组] 金明的预算方案 - 洛谷

// 有依赖的背包 O(nm)
#include<bits/stdc++.h>  
using namespace std;

int n,m;
int zv[65],zw[65],fv[65][3],fw[65][3];
int f[32005];

int main(){
  cin>>m>>n;      //m总钱数, n总个数
  for(int i=1,v,p,q; i<=n; i++){
    cin>>v>>p>>q; //价格 重要度 对应的主件
    if(!q){
      zv[i]=v;    //主件价格
      zw[i]=v*p;  //主件价值
    }  
    else{
      ++fv[q][0];           //附件个数
      fv[q][fv[q][0]]=v;    //fv附件价格
      fw[q][fv[q][0]]=v*p;  //fw附件价值
    }
  }
  
  for(int i=1; i<=n; i++) if(zv[i]){    //如果第i个物品是主件
    for(int j=m; j>=zv[i]; j--){        //价格
      f[j]=max(f[j],f[j-zv[i]]+zw[i]);  //只选主件
      if(j>=zv[i]+fv[i][1])             //选主件+a
        f[j]=max(f[j],f[j-zv[i]-fv[i][1]]+zw[i]+fw[i][1]);
      if(j>=zv[i]+fv[i][2])             //选主件+b
        f[j]=max(f[j],f[j-zv[i]-fv[i][2]]+zw[i]+fw[i][2]); 
      if(j>=zv[i]+fv[i][1]+fv[i][2])    //选主件+a+b
        f[j]=max(f[j],f[j-zv[i]-fv[i][1]-fv[i][2]]+zw[i]+fw[i][1]+fw[i][2]);  
    }
  }
  cout<<f[m]; 
}

 

posted @ 2023-04-10 10:01  董晓  阅读(1092)  评论(1)    收藏  举报