1. 程式人生 > 其它 >揹包九講(7)

揹包九講(7)

揹包九講(7)

有依賴的揹包問題

有 N 個物品和一個容量是 V的揹包。

物品之間具有依賴關係,且依賴關係組成一棵樹的形狀。如果選擇一個物品,則必須選擇它的父節點。

如下圖所示:

如果選擇物品5,則必須選擇物品1和2。這是因為2是5的父節點,1是2的父節點。

每件物品的編號是 ii,體積是 vi,價值是 wi,依賴的父節點編號是 pi。物品的下標範圍是 1…N。

求解將哪些物品裝入揹包,可使物品總體積不超過揹包容量,且總價值最大。

輸出最大價值。

輸入格式

第一行有兩個整數 N,V,用空格隔開,分別表示物品個數和揹包容量。

接下來有 N 行資料,每行資料表示一個物品。
第 ii 行有三個整數 vi,wi,pi,用空格隔開,分別表示物品的體積、價值和依賴的物品編號。
如果 pi=−1,表示根節點。 資料保證所有物品構成一棵樹。

輸出格式

輸出一個整數,表示最大價值。

資料範圍

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

父節點編號範圍:

  • 內部結點:1≤pi≤N
  • 根節點 pi=−1

輸入樣例

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

輸出樣例:

11

沒看懂,暫時放上別人的解答,以後再考慮

AcWing 10. 有依賴的揹包問題(思路不同於dxc,但是個人感覺更好理解) - AcWing

#include<iostream>
#include<vector>
using namespace std;
int f[110][110];//f[x][v]表達選擇以x為子樹的物品,在容量不超過v時所獲得的最大價值
vector<int> g[110];
int v[110],w[110];
int n,m,root;

int dfs(int x)
{
    for(int i=v[x];i<=m;i++) f[x][i]=w[x];//點x必須選,所以初始化f[x][v[x] ~ m]= w[x]
    for(int i=0;i<g[x].size();i++)
    {
        int y=g[x][i];
        dfs(y);
        for(int j=m;j>=v[x];j--)//j的範圍為v[x]~m, 小於v[x]無法選擇以x為子樹的物品
        {
            for(int k=0;k<=j-v[x];k++)//分給子樹y的空間不能大於j-v[x],不然都無法選根物品x
            {
                f[x][j]=max(f[x][j],f[x][j-k]+f[y][k]);
            }
        }
    }
}

int main()
{
    cin>>n>>m;
    for(int i=1;i<=n;i++)
    {
        int fa;
        cin>>v[i]>>w[i]>>fa;
        if(fa==-1)
            root=i;
        else
            g[fa].push_back(i);
    }
    dfs(root);
    cout<<f[root][m];
    return 0;
}