poj 2184

哎,我反正是想不到是01背包。。。
最多100个物品,每个物品 价值 和 重量 都是 [ 1000 , 1000 ] ,所以重量最多是 [ 100 1000 , 100 1000 ] 但是背包不能是负的,就加都加100000变成 [ 0 , 200000 ] ,所以背包最大空间 W 就是200000

但是,一下几点我不是很理解:
①为什么dp初值要赋值为
②为什么重量是负的时候,用的完全背包?而且并不是像模板一样从 c W

后来有点理解:
①:因为我们的 d p [ i ] 可能是负的,你看最后都还要找 d p [ i ] > 0 的,所以初值就不能比 0 大,那取好小合适喃?最坏情况就是 100 个都是 1000 ,那至少要取 1000000 才合适,所以懒得了,直接
②:这个就要从01背包为啥是倒起来说了,阔以看哈这个
比如我们来了一个重量 c = 3 ,价值为 v ,假如计算 d p [ 10 ] ,
那么 d p [ 10 ] = m a x ( d p [ 10 ] , d p [ 10 3 ] + v )
即: d p [ 10 ] = m a x ( d p [ 10 ] , d p [ 7 ] + v )
因为是倒起来,计算 d p [ 10 ] 的时候, d p [ 7 ] 还没有更新过,所以还是上一次状态,所以倒起来是对的,这是我们正常的背包嘛~

But:

假如来了一个重量 c = 3 的东西
那么 d p [ 10 ] = m a x ( d p [ 10 ] , d p [ 10 ( 3 ) ] + v )
即: d p [ 10 ] = m a x ( d p [ 10 ] , d p [ 13 ] + v )
如果倒起来,这样计算 d p [ 10 ] 的时候, d p [ 13 ] 却已经更新过了,所以不是上一次的状态,这样不对
但是这个时候正起来就对了
所以正起来看起来像完全背包,但是其实并不是,其实他还是01背包,网上有人说小于0就是完全背包,我就说咋就变成完全背包了嘛,死活理解不到。。。

#include"iostream"
#include"cstring"
using namespace std;
const int maxn=2e5+5;
int dp[maxn];
int inf=1e9;
int sh=100000;
int W=2e5;
int N;
void bag01(int v,int c)
{
    if(c>0)for(int i=W;i>=c;i--)dp[i]=max(dp[i],dp[i-c]+v);
    else for(int i=0;i<W+c;i++)dp[i]=max(dp[i],dp[i-c]+v);
}
int main()
{
    while(cin>>N)
    {
        for(int i=0;i<=W;i++)dp[i]=-inf;
        dp[sh]=0;
        for(int i=1;i<=N;i++)
        {
            int v,c;
            cin>>c>>v;
            bag01(v,c);
        }
        int ans=0;
        for(int i=sh;i<=W;i++)//相当于只要正的那一坨
        {
            if(dp[i]>0)ans=max(ans,i+dp[i]-sh);//取v+c最大的
        }
        cout<<ans<<endl;
    }
}

猜你喜欢

转载自blog.csdn.net/swustlpf/article/details/80069474