zoukankan      html  css  js  c++  java
  • 01背包的变形

          我弟弟搞OI,问了我一道OI的题目,一看01背包,一做就是一上午。还是对01背包又忘记了。

          题目链接:点击打开链接

          

         01背包,之前博文有代码+讲解,再此就不赘余了。这道题目有主附件关系,但因为附件最多只有2件 ,所以主附件的组合最多4种,分别为

                                               

    然后进行01背包,我们为了方便 把这4种方案放在结构体中;

    伪代码:

    void pack_01()
    {
        for(int i=(背包容量);i>0;i--)
        {
            for(int x=0;x< (某一个主附件方案数);x++)
            {
                if(i- (某种方案的weight) >=0)//为了保证下面一行dp的下标为自然数
                dp[i]=max(dp[i],dp[i-(某种方案的weight)]+(某种方案的value));
            }
        }
    }

    你们或许会有一个问题,就是:这样怎么能够让属于同一类方案的只选择一个?

      dp数组里面,我们需要往前面进行状态转移!我们转移是4种方案,同时进行往前更新dp,这样转移是从上一个一大类方案中转移过来的。所以不会出现多个同为一个主件。

    存数据,最好是结构体中,这样比较方便看;


    /************************************************************/
    /**         Reproduced please indicate the source          **/
    /************************************************************/
    
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    
    struct item
    {
        int v[4],w[4],c;//4种方案的花费, 价值;
    };
    item pack[65];
    int ind[65];//下标索引,因为数据存的时候不是连续的;
    int dp[3500];
    void pack_01(int num,int n)
    {
        for(int i=n; i>=0; i--)
        {
            for(int x=0; x<pack[num].c; x++)
            {
                if(i-pack[num].v[x]>=0)
                    dp[i]=max(dp[i],dp[i-pack[num].v[x]]+pack[num].w[x]);
            }
        }
    }
    int main(void)
    {
        int n,m,j;
        memset(dp,0,sizeof(dp));
        scanf("%d%d",&n,&m);
        j=1;
        n/=10;
        for(int i=1; i<=m; i++)
        {
            int v,p,q;
            scanf("%d%d%d",&v,&p,&q);
            v/=10;
            if(q==0)//如果是主件,存在 0 数组
            {
                pack[j].v[0]=v;
                pack[j].w[0]=p*v;
                pack[j].c=1;
                ind[i]=j;
                j++;
            }
            else//如果不是主件;
            {
                q=ind[q];
                if(pack[q].c==1)
                {
                    pack[q].v[1]=pack[q].v[0]+v;
                    pack[q].w[1]=pack[q].w[0]+v*p;
                    pack[q].c=2;
                }
                else if(pack[q].c==2)//附件有两个
                {
                    pack[q].v[2]=pack[q].v[0]+v;
                    pack[q].w[2]=pack[q].w[0]+v*p;
                    pack[q].v[3]=pack[q].v[1]+v;
                    pack[q].w[3]=pack[q].w[1]+v*p;
                    pack[q].c=4;
                }
            }
        }
        
        for(int i=1; i<j; i++)
            pack_01(i,n);
        printf("%d
    ",dp[n]*10);
        return 0;
    }




  • 相关阅读:
    每日总结
    每日总结
    团队冲刺阶段二(10)
    团队冲刺阶段二(9)
    团队冲刺阶段二(8)
    团队冲刺阶段二(7)
    团队冲刺阶段二(6)
    团队冲刺阶段二(5)
    团队冲刺阶段二(4)
    根据Panda Global了解,中央政治局第十八次集体学习中指出“区块链技术的集成应用在新的技术革新和产业变革中起着重要作用”
  • 原文地址:https://www.cnblogs.com/coded-ream/p/7207959.html
Copyright © 2011-2022 走看看