ACM算法笔记(三)背包问题_完全背包

首发csdn,链接:https://blog.csdn.net/Colicsin/article/details/115404392?spm=1001.2014.3001.5501

问题描述:

现在给你一个容量为V的背包,有N个物品,其中第i件物品的重量为wi,价值为vi,每件物品可以拿无数次,问在有限的容量内,最多可以拿到多少价值的物品。

题目分析:

完全背包问题和01背包好相似诶,不过貌似又不是那么一样,对于完全背包问题的每一个物品不是两种状态了,而是k+1种状态:不拿或者拿1件或者拿2件或者....


刚开始看到完全背包的问题描述的时候,笔者脑海中还是蛮开心的,这不就是贪心吗?那我直接求性价比,用现在的包裹全部装性价比最高的,然后用剩下的装性价比第二高的...以此类推不就行了嘛。然而理想是美好的,但现实往往就是那么残酷QAQ

稍微举了个小案例,就发现貌似并不可以(当然不可以,不然还要dp干啥...想想还是挺有道理的orz)就拿一个例子来说:两个物品分别是5 5和8 7(分别表示重量和价值),背包是10要是按照贪心策略,那肯定是7了,但是答案却是5+5=10。

好吧,贪心确实不好用。(蒟蒻的怒吼~)

还记得之前讲过的01背包问题吗?当时在用滚动数组的思想去优化的时候,是不是出现了正序和倒序的问题?当时模拟了一遍中间过程,发现不能正序,因为正序会导致某一个物品被反复选择...诶!这不正好是我们现在想要的吗?(雀食蟀啊)

所以说其实就只要吧01背包的倒序改为正序就变成了完全背包问题了,至于原因,还是见01背包问题关于倒序的手动模拟部分

果然是车到山前必有路、世界是普遍联系的、联系具有客观性、条件性、多样性....(此人已疯不用搭理qwq)

所以我们只需要把倒序改为正序,就可以咯,代码如下...

#include
#include
#include
using namespace std;
const int MAXN=1e3+7;
int w[MAXN],N,V,v[MAXN],dp[100001];
int main()
{
    memset(dp,0,sizeof(dp));
    cin>>V>>N;
    for(int i=1;i<=N;i++)
    {
        cin>>w[i]>>v[i];
    }
    for(int i=1;i<=N;i++)
    {
        for(int j=0;j<=V;j++)
        {
            if(j>=w[i])
                dp[j]=max(dp[j],dp[j-w[i]]+v[i]);   
        }
    }
    cout<

完全背包问题,结束~

你可能感兴趣的:(ACM算法笔记(三)背包问题_完全背包)