[Learning] grouping algorithm knapsack problem

There are N items V and a capacity of the backpack, the weight of the i-th items of W [i], the value of V [i], the items are divided into multiple groups, each group of conflicting items, selected from the most one
asked what the items into the backpack can cause the backpack to get the most value

For each group of items, it can be seen as a 01 knapsack problem, for each group of items can be processed once.

Input format:
first line: three integers, V (backpack capacity, V <= 200), N ( the number of items, N <= 30) and T (maximum group number, T <= 10);
second 2 ... N + line 1: each line three integers Wi, Vi, p, represents a weight value, belongs to the group number of each item.
From the idea of this blog referenced
Blog reference
if the performance of a two-dimensional array of forms:

  1. Number of group cycling
  2. Select items
  3. Volume cycle
    // 二维数组:
    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]] );  //求组这组最大

Wherein, f[k-1][j]referring to k-1 before the maximum value j volume group, and therefore v[k][i] + f[k-1][j-w[k][i]]means: taking the current set before the i + k-1 articles volume group jw [k] [i] (left button on the volume of out the current value of the volume of goods) value.

To one-dimensional words:

  1. The number of packets Group
  2. Volume cycle
  3. Traversal of goods
    // 一维数组 :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]] ); //价值为
            }

Among them, the following general took the form of a one-dimensional array.
Code and input values can refer to this blog

#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;

}


Published 63 original articles · won praise 13 · views 40000 +

Guess you like

Origin blog.csdn.net/changreal/article/details/102582162