• 完全背包


    处理何种问题:给定 n 种物品(每种类型无限)和一个容量为 V 的背包,物品 i 的体积为 vi,其价 值为 pi,求其最终可以装进背包的物品最大价值。

     

    性能:时间复杂度为O(nV)。

     

    原理:在学习背包之前,可能是思考方向的不对的原因,导致对背包题解的做法有些误解,现在借着写完全背包我在这里阐述一下我对于背包的理解。

    在此,我先假定一个数组dp[V],里面存的是当背包容量只有V的情况下,可以存的物品的最大价值是多少。然后,我们假设只有第一件物品arr[0],然后我们利用arr[0],对dp[V]进行赋值操作,如下图所示:

    dp[0]

    dp[arr[0].v]

    dp[arr[0].v+1]

    dp[arr[0].v*2]

    dp[V]

    0

    arr[0].p

    arr[0].p

    arr[0].p*2

    V/arr[0].v*arr[i].p

    然后,我在dp[V]已更新的基础上我们再加上一个物品arr[1],对此我们依旧仿照上面的操作判断dp[V]=max(dp[V],dp[V-arr[1].v]+arr[1].p),毕竟我们只需要确保当背包为V时,看看怎么加物品i使得dp[V]最大(是放还是不放),这是一个迭代的过程,dp[V-arr[1].v]+arr[1].p就是为了得到在放该物品之后能得到的最大值。

    在捋清思路之后,完全背包的解法就是这么显得顺其自然,很像贪心。

     

    实现步骤:与01背包类似,具体看代码。

     

    备注:状态转移方程具体看代码,个人觉得与01背包相似,但又有一些根本上的不同,在这里就不写了。

     

    输入样例解释

    5 1000 //n种物品,背包容量为V

    144 990//第0种物品的体积和价值

    487 436

    210 673

    567 58

    1056 897

    输出样例解释

    5940 //最大价值

    #include<iostream>
    #include<cstdio>
    #include<string.h>
    #include<algorithm>
    using namespace std;
    
    struct node
    {
        int v,p;
    };
    node arr[11000];
    int dp[100010];
    
    int main()
    {
        int n,V;
        memset(dp,0,sizeof(dp));
        scanf("%d%d",&n,&V);
    
        for(int i=0;i<n;++i)    scanf("%d%d",&arr[i].v,&arr[i].p);
    
        for(int i=0;i<n;++i)
        {
            for(int j=arr[i].v;j<=V;++j)
            {
                dp[j]=max(dp[j],dp[j-arr[i].v]+arr[i].p);
            }
        }
    
        printf("%d
    ",dp[V]);
        return 0;
    }
    

      

  • 相关阅读:
    Bookmarks_www2
    Linux系统各发行版镜像下载(持续更新)
    tiny-rtems-src
    rtems-os-source
    OpenRCT2-ext
    PAT甲级1004题解——并查集思想改
    PAT甲级1008水题飘过
    PAT甲级1007题解——贪心
    PAT甲级1006水题飘过
    PAT甲级1005水题飘过
  • 原文地址:https://www.cnblogs.com/l1l1/p/9495252.html
Copyright © 2020-2023  润新知