畅谈分组背包问题

简介: 畅谈分组背包问题

分组背包问题是背包问题的一种变体,它在一组物品中进行选择,每个物品属于某个特定的组。问题的描述通常是这样的:给定若干组物品,每组物品都有自己的重量、价值以及数量限制。目标是选择若干组物品放入背包中,使得背包中物品的总价值最大。

这里用acwing上的例题:9. 分组背包问题 - AcWing题库


朴素解法

这里朴素解法利用的二维数组f[i][j]来进行状态转移,枚举物品组数,枚举体积,枚举对于每组物品的决策,选还是不选,以得到最优解。这里朴素解法不再详细介绍,只放一个代码段,因为后面还可以优化一下。


其实看起来跟多重背包的朴素解法差不多,有什么不同的,下面放上了两段代码,比较看一下。不同在了就是在状态转移上了,多重背包呢可以选多个所以用k来控制,分组背包呢,例题中一组背包中最多只允许选一个,就是对于一组背包可以不选可以选一个。每一个物品都是不同的、有个性的,没有完全相同的,第三个for循环就是在枚举每一组具体的物品。


一维优化解法

对照朴素解法,多重背包呢时间复杂度那个for循环k的可以优化掉,空间复杂度也可以优化成一维的,但是时间复杂度优化是有条件的,多重背包呢可以组合进行二进制优化,也可以分类进行单调队列优化。分组背包呢,第i组物品的体积价值都是各不相同的,毫无规律可言,何以优化,但是在空间复杂度上可以优化成一维,f[i][j]是在f[i-1][j]转移过来的,就是在前一组物品决策完转移过来的,只是用了上一行的数据,有点类似01背包的一维优化。

#include<iostream>
using namespace std;
int dp[1005],v[1005],w[1005];//dp[i]表示背包容量为i时所获得最大价值
int N,V;
int main(){
  cin>>N>>V;
  int p;//p表示第p组物品
  for(int i=1;i<=N;i++){
    cin>>p;
    for(int j=1;j<=p;j++){
      cin>>v[j]>>w[j];
    }
        //因为dp[j]会先于dp[j-v[k]]更新,所以dp[j-v[k]]的值等价于dp[i-1][j-v[k]]
    for(int j=V;j>=1;j--){//逆序枚举背包容量
      for(int k=1;k<=p;k++){
        if(j>=v[k]){
          dp[j]=max(dp[j],dp[j-v[k]]+w[k]);
        }
      }
    }
  }
  cout<<dp[V]<<endl;
  return 0;
}

这里注意枚举背包容量和枚举k顺序不可颠倒,不然dp[j-v[k]]的值就不等价于dp[i-1][j-v[k]]了。


变式题型

小编做过其他类型的题,但都是分组背包的变式。有的题呢,一组物品给你限定了选多少个,比如选2个3个,例题中最多选一个,这样的话就比较麻烦了,既要确定选了哪一组物品又要达到选几个的要求,还是再次基础上,利用贪心,在每一组背包选几个的要求基础上,使得每一组背包都是最优的就可以(01背包)。用背包容量去枚举每一组背包,再去加一个if判断是否达到选几个的要求。有的呢还会物品会乱序输入,让你自己去分组好,再去进行选择。下面放一个我写过的题的代码,组数打乱自己找的(当然题中样例每打乱)。

#include<iostream>
#include<vector>
using namespace std;
int w[31],c[31];
int dp[201];
int v,n,p,t;
int main(){
  cin>>v>>n>>t;//v容量n物品t组数
  vector<vector<int>> group(t+1);
  for(int i=1;i<=n;i++){
    cin>>w[i]>>c[i]>>p;//p属于第几组
    group[p].push_back(i);//把下标往里抛就行
  }
  for(int i=1;i<=t;i++){//与一维优化类似
    for(int j=v;j>=0;j--){
      for(int k=0;k<group[i].size();k++){
        int index=group[i][k];
        if(j>=w[index]){
          dp[j]=max(dp[j],dp[j-w[index]]+c[index]);
        }
      }
    }
  }
  cout<<dp[v]<<endl;
  return 0;
}
/*
10 6 3
2 1 1
3 3 1
4 8 2
6 9 2
2 8 3
3 9 3
*/
//20

分组背包呢,听起来就是分组分组……,无非还是01背包的变形,背包问题呢,变形非常多,但是万变不离其宗,方法会了,其他变式也都迎刃而解。小编水平有限,能说的都在文章展现了,有错误的地方请大家指出,大家有疑问的地方随时可以私信我,看到必答。下篇更新有依赖的背包。

相关文章
|
测试技术
蓝桥 晚会节目单 (线段树)
蓝桥 晚会节目单 (线段树)
|
算法 C语言 C++
【数论】蚂蚁感冒、饮料换购、买不到的数目
长 100 厘米的细长直杆子上有 n只蚂蚁。
95 0
|
存储 人工智能 算法
【蓝桥杯集训·每日一题】AcWing 3305. 作物杂交
文章目录 一、题目 1、原题链接 2、题目描述 二、解题报告 1、思路分析 2、时间复杂度 3、代码详解 三、知识风暴 Spfa算法
130 0
|
决策智能
LDU20级新生排位赛第二场
LDU20级新生排位赛第二场
138 0
LDU20级新生排位赛第二场
|
人工智能
牛客-xinjun与阴阳师(分组背包)
牛客-xinjun与阴阳师(分组背包)
106 0
|
网络架构
运动会-组合数学
题目描述 在一次运会上,有一个比赛项目,共有N个人参加比赛,要将这N个人分组,每组人数不少于K个,问有多少种分组方式? 比如有16个运动员,每组人数不少于5个,共有6种分组方式: (1) 分一组,为16人; (2) 分二组,分别为11人、5人; (3) 分二组,分别为10人、6人; (4) 分二组,分别为9人、7人; (5) 分二组,分别为8人、8人; (6) 分三组,分别为6人、5人、5人。 注意:6+5+5,5+6+5,5+5+6为同一种,只算一种分组方式; 输入 输入共一行为两个整数N, K。表示有N个运动员分组,每组不少于K个人(1 ≤ K ≤ N ≤ 500)。
186 0
解救被困传销女演员 助人减肥找老婆 蚂蚁森林又现神功能
近日,一篇《女演员被传销组织拘禁30多天 竟因蚂蚁森林幸运逃离》的报道引发了全网热议。网友纷纷表示:蚂蚁森林功能强大,不仅能帮人减肥、找老婆,还能在关键时刻保命!
5446 0