完全背包

处理何种问题:给定 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\n",dp[V]);
    return 0;
}

  

posted @ 2018-08-17 20:49  逃往火星的猫  阅读(142)  评论(0编辑  收藏  举报