AcWing has a dependent backpack problem

10. Dependent knapsack problem

Title

There are N items and a backpack with a capacity of V.

There is a dependency relationship between items, and the dependency relationship forms the shape of a tree. If you select an item, you must select its parent node.
Insert picture description here

If you select item 5, you must select items 1 and 2. This is because 2 is the parent node of 5 and 1 is the parent> node of 2.

The number of each item is i, the volume is vi, the value is wi, and the dependent parent node number is pi. The subscript range of the item is 1...N.
Solve which items are loaded into the backpack, so that the total volume of the items does not exceed the capacity of the backpack, and the total value is the largest.
Output the maximum value.

Input format

There are two integers N and V in the first line, separated by a space, indicating the number of items and the capacity of the backpack, respectively.
Next, there are N rows of data, each row of data represents an item.
There are three integers vi, wi, and pi in the ith row, separated by spaces, indicating the volume, value, and dependent item number of the item.
If pi=−1, it means the root node. The data guarantees that all items constitute a tree.

Output format

Output an integer that represents the maximum value.

data range

1≤N,V≤100
1≤vi,wi≤100

Parent node number range:

Internal node: 1≤pi≤N;
root node pi=−1;

Input sample

5 7
2 3 -1
2 2 1
3 5 1
4 7 2
3 6 2

Sample output

11

Question meaning analysis:

The entry order of each item is the subscript, from 1-n

Assuming that there is only one main part and multiple n other attachments, then there can be 2^n (permutation and combination) sets of main parts and attachments, that is, the solution is in these strategies

Enumerating 2^n may be obviously unrealistic. We can consider "a simple optimization", that is, 01 backpack. Under the premise that the main part has been selected, use 01 backpack to select the most other accessories (select or not for each accessory). Excellent solution

Because the 01 backpack "same volume but high value" filters out useless strategies, so the positive solution is a code in dp[j] with fn[key][j]

Contact question meaning (tree): The attachment of each main piece may be the main piece of another object (as long as the main piece of an object (not the root) has been selected in the question, this object can be selected), so each attachment It is also a collection. By first finding its own collection of attachments (attachments are collections), through the different sizes you allocate to the attachments, this attachment will have different benefits.

Therefore, when using the 01 backpack to select accessories, add an internal loop and re-enumerate the accessories (the accessories themselves are also a tree) to allocate the benefits corresponding to different volumes/to get the optimal strategy for backpack benefits in different sizes.

So how to find the optimal strategy for its attachments corresponding to the different allocated volumes?
Directly using the recursive nature of the tree, each time the optimal strategy for a set of different volumes is sought, the optimal strategy for the accessories allocated to different volumes can be found first.

Code can run within 18ms

#include <iostream>
using namespace std;
const int N =200;
int fn[N][N];
int p[N],v[N],w[N];
int n,V;               
int fun(int key,int VV){
    
    //key主件下标 VV可分配的体积
   //递归的求01
   if(VV<v[key])//没有体积选择这个物件 
        return 0;
    for(int i = 1;i <= n;i++)//对附件进行递归
        if(p[i] == key)//如果是它的附件 
            fun(i,VV-v[key]);

    fn[key][v[key]] = w[key];//先选择主件, 选了主件才能选择对应的附件 
    
    for(int i = 0;i <= n;i++){
    
    //01背包 对不同体积求 最大价值 
        if(p[i] == key)//如果是主件的附件 
            for(int j = VV;j>=v[key];j--){
    
    //从体积最大开始  确保每个附件其对应的集合只能选择一个次 
                for(int j1 = 0;j1 <=j-v[key];j1++ )//可支配体积
                    if(fn[key][j-j1] && fn[i][j1])//当已经选了主件,并且分配给附件的体积是可以得到有意义的价值的 
                        fn[key][j] = max(fn[key][j],fn[key][j-j1]+fn[i][j1]);//更新可能的价值 
            }
    }
  
}

int main(){
    
    
   
    cin >> n >>V;
    int key;
    for(int i = 1;i <= n;i++){
    
    
        cin >> v[i] >> w[i] >> p[i];
        if(p[i] == -1)
            key = i;//获得根结点的下标
    }
        
    fun(key,V);//结点, 和可支配的体积
    int result = 0;
    for(int j = 0;j <=V;j++)//从不同体积的最优策略中选择 价值最大的策略 
        result = max(result,fn[key][j]);
    cout << result << endl;
    return 0;
}


Guess you like

Origin blog.csdn.net/RunningBeef/article/details/111416061