acwing 10. 有依赖的背包问题

放肆的年华 提交于 2020-01-12 02:24:21

传送门

有 N 个物品和一个容量是 V 的背包。

物品之间具有依赖关系,且依赖关系组成一棵树的形状。如果选择一个物品,则必须选择它的父节点。

如下图所示:
QQ图片20181018170337.png

如果选择物品5,则必须选择物品1和2。这是因为2是5的父节点,1是2的父节点。

每件物品的编号是 i,体积是 vi,价值是 wi,依赖的父节点编号是 pi。物品的下标范围是 1…N。

求解将哪些物品装入背包,可使物品总体积不超过背包容量,且总价值最大。

输出最大价值。

输入格式

第一行有两个整数 N,V,用空格隔开,分别表示物品个数和背包容量。

接下来有 N 行数据,每行数据表示一个物品。

第 i 行有三个整数 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

对于这个我们首先找到根节点,然后遍历根节点连接的点,对于每个点递归进行同样的操作,然后对于同一个根节点的点组算一下最大值即可。

AC代码如下:
#include<bits/stdc++.h>
using namespace std;
const int N=110;
int n, m;
int h[N], e[N], ne[N], idx;
int v[N], w[N];
int f[N][N];
inline int read(int &n)
{
    int x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    n = x * f;
}
void add(int x, int y) {
    e[idx] = y, ne[idx] = h[x], h[x] = idx++;
}

void dfs(int x) {
    for (int i = h[x]; i != -1; i = ne[i]) {
        int y = e[i];
        dfs(y);
        for (int j = m - v[x]; j >= 0; j--) {
            for (int k = 0; k <= j; k++) {
                f[x][j] = max(f[x][j], f[x][j - k] + f[y][k]);
            }
        }
    }
    for (int i = m; i >= v[x]; i--)    f[x][i] = f[x][i - v[x]] + w[x];  //必须要将根节点放进去
    for (int i = 0; i < v[x]; i++)    f[x][i] = 0;   
}

int main() {
    memset(h, -1, sizeof h);
    read(n),read(m);
    int root;
    for (int i = 1; i <= n; i++) {
        int p;
        read(v[i]), read(w[i]), read(p);
        if (p == -1)   root = i;
        else     add(p, i);
    }
    dfs(root);
    cout << f[root][m] << endl;
    return 0;
}
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!