zoukankan      html  css  js  c++  java
  • (金明的预算方案)依赖性的背包

    例题的话,可以看一下洛谷1064 金明的预算方案

    原题链接 https://www.luogu.org/problemnew/show/P1064

    有依赖性的背包,顾名思义,及选中其中一个物品,另一个物品必须随之选择

    题意:

    有n个物品,预算为V元,w[i]为每个物品的价格,v[i]为每个物品的重要程度,c[i]为每个数的主件,

    如果c[i]为0,则代表该物品为主件,否则为c[i]的附件,每个物品的价值为w[i]*v[i],求最大的价值。

    这就是典型的依赖性背包,我们可以首先可以用01背包的思想预处理出4种情况

    1.只选择主件

    2.选择主件且选择附件1 

    3.选择主件且选择附件2 

    4选择主件且选择附件1和附件2

    这就是一个01背包,题目中保证每个主件只有两个附件,所以讲处理过的放入vector中,

    接下来就是分组背包,因为选择了其中一种情况是不可能在选择其他的情况的

    这题就可以a掉了

    注意!!!

    1.在预处理时不要忘了把主件加进去。

    2.预处理出来如果一种情况与另一种情况的价值一样,则价格小的一定是最优的,见代码注释

    #include <cstdio>
    #include <cstdlib>
    #include <vector>
    #include <iostream>
    #include <algorithm>
    #include <cstring>
    using namespace std;
    const int N=60;
    struct node
    {
        int w,v;
        node(int ww,int vv)
        {
            w=ww,v=vv;
        }
    };
    vector <node> g[N],g1[N];
    int n,V,v[N],w[N],c[N],dp[200005];
    int main()
    {
        scanf("%d %d",&V,&n);
        for(int i=1;i<=n;i++)
        {
            scanf("%d %d %d",&w[i],&v[i],&c[i]);
            v[i]=v[i]*w[i];
            if(c[i])
                g[c[i]].push_back(node(w[i],v[i]));
        }
        for(int i=1;i<=n;i++)
        {
            if(!g[i].empty())
            {
                memset(dp,0,sizeof(dp));
                for(int k=0;k<g[i].size();k++)
                {
                    for(int j=V-w[i];j>=g[i][k].w;j--)
                    {
                        dp[j]=max(dp[j],dp[j-g[i][k].w]+g[i][k].v);//01背包
                    }
                }
                for(int j=1;j<=V-w[i];j++)
                {
                    if(dp[j] && dp[j-1]!=dp[j])//此处为注意的第二点
                        g1[i].push_back(node(w[i]+j,dp[j]+v[i]));
                }
                g1[i].push_back(node(w[i],v[i])); //此处为注意的第一点
            }
            else if(!c[i])
            {
                g1[i].push_back(node(w[i],v[i]));//此处也为注意的第一点
            }
        }
        memset(dp,0,sizeof(dp));
        for(int i=1;i<=n;i++)//分组背包
        {
            for(int j=V;j>=0;j--)
            {
                for(int k=0;k<g1[i].size();k++)
                {
                    if(j>=g1[i][k].w)
                        dp[j]=max(dp[j],dp[j-g1[i][k].w]+g1[i][k].v);
                }
            }
        }
        printf("%d
    ",dp[V]);
        return 0;
    }

    我居然写了两个小时,还是我太蒻了

  • 相关阅读:
    继承与多态——动手又动脑
    类与对象--动手又动脑
    Go语言接口
    GO语言结构体
    GO指针
    GO函数
    GO获取随机数
    GO基础
    Go语言的%d,%p,%v等占位符的使用
    GO语言常量和变量
  • 原文地址:https://www.cnblogs.com/wzrdl/p/9773854.html
Copyright © 2011-2022 走看看