【算法学习】分组背包问题

有N件物品和一个容量为V的背包,第i件物品的重量为w[i],价值为v[i],这些物品被划分成了若干组,每组中的物品互相冲突,最多选一件
问将哪些物品放入背包中可以使背包获得最大的价值

对于每一组的物品,都可以看成是一个01背包问题,对每组的物品都处理一遍即可。

输入格式:
第一行:三个整数,V(背包容量,V<=200),N(物品数量,N<=30)和T(最大组号,T<=10);
第2…N+1行:每行三个整数Wi,Vi,p,表示每个物品的重量,价值,所属组号。
这篇博客参考的思路
博客参考
若是二维数组的表现形式:

  1. 组数循环
  2. 物品选择
  3. 体积循环
    // 二维数组:
    f[k][j]表示前k组体积为j的最大价值
    for(int k=1; k<=T; ++k)            //组别
        for(int i=1; i<=N; ++i)       //物品
            for(int j=V; j>=0; j--)   //体积
                f[k][j] = max(f[k][j], v[k][i]+f[k-1][j-w[k][i]] );  //求组这组最大

其中,f[k-1][j] 指的是前k-1组体积为j的最大价值,因此v[k][i] + f[k-1][j-w[k][i]]意思是:取当前这组第i个物品 + 前k-1组体积为j-w[k][i](体积就还剩扣掉当前物品的体积的值)的价值。

到一维的话:

  1. 分组组数
  2. 体积循环
  3. 对物品进行遍历
    // 一维数组 :f[j]表示体积为j的时候的最大价值!(每组都共用一个dp数组,dp数组保存最大价值)
    for(int k=1; k<=T;k++)
        for(int j=V; j>=0; j--)   //分组体积
            for(int i=1; i<=a[k][0]; i++){  //对体积里的每个物品
                int x = a[k][i]; //x来记录物品编号
                if(j>=w[i])  //容量大于第i个物品的体积
                    f[j] = max(f[j], v[x]+f[j-w[x]] ); //价值为
            }

其中,以下总体用了一维数组的形式。
代码和输入值可以参考这篇博客

#include<iostream>
#include<algorithm>
#include <vector>
#include<cstring> 
using namespace std;
const int maxn=105;
const int maxv=105;
const int maxt=15;
int N,V,T;
int v[maxn], w[maxn];
int dp[maxv]; //f存的是代价函数,因此以v为单位,f的意思是容量为c时该组取所需元素的最大值
int groupitem[maxt][maxn]; //a存放的是分组t里的物品编号

int main(){

    cin>>V>>N>>T;
   memset(&groupitem, 0, sizeof(groupitem)); //这一步似乎可有可无

    // 输入
    for(int i=1; i<=N; ++i){
        int p;
        cin>>w[i]>>v[i]>>p;
        groupitem[p][++groupitem[p][0]] = i;  //groupitem[p][0]来存放该组的数量
    }

    // 开始求解,分别是①对组;②对每组来说的容量;③对该组内的物品进行~
    for(int i=1; i<=T; ++i){
        for(int j=V; j>=0; --j)
            for(int k=1; k<=groupitem[i][0]; k++){
                int x = groupitem[i][k]; // 获取当前组的物品编号
                //记得if语句判断一下:
                if( j>=w[x] )
                    dp[j] = max(dp[j], v[x] + dp[j-w[x]]); //一维的写法,  关键是f[j-w[x]]去掉
            }
    }
    cout<<dp[V]<<endl; //从而输出:容量为j的时候

    return 0;

}


发布了63 篇原创文章 · 获赞 13 · 访问量 4万+

猜你喜欢

转载自blog.csdn.net/changreal/article/details/102582162
今日推荐