01背包问题 与 完全背包

一、01背包

事例:

有N件物品和一个容量为V的背包。第i件物品所占用容量是v[i],价值是w[i]。求将哪些物品装入背包可使总价值最大。

思路:

  1. 要使装入背包内的物品价值最大,应优先装入占地空间小且价值大的物品。
  2. 我们不妨先找出容积从0到V 的各个容量所装物品的最优解。(就是指 当背包容量为1时装物品的最优解,当背包容量为2时装物品的最优解······一直到容积为N时装物品的最优解)。
  3. 那么如何求在容积为 v 时的最优解呢。那么就是把每种情况都放一下找出最优的。此时要用到的公式是f[j]=max(f[j],f[j-weight[i]]+value[i]);
  4. 下面来讲解一下该公式的含义

    f[j] 含义是当背包容量为 j 时的价值最优解(即怎样放物品能使背包总价值最大)。

    f[j-weight[i]] 含义是在放入第i件物品前背包价值的最优解。

    那么f[j-weight[i]]+value[i] 的含义就很简单了,即放入第i件物品时背包的价值。

    max(f[j],f[j-weight[i]]+value[i]) 就是比较原本背包容量为 j 时的最大价值与现在放第i件物品时背包价值,取最大值成为新的“背包容量为j时的最优解”(我们可以评出的看到背包的容量一直 j,没有改变)。

代码:

#include <iostream>
#include <cstring>
using namespace std;

const int N=4; //一共有N件物品。
const int V=5; //背包容量为V。
int weight[N]={1,2,2,3}; //各个物品的体积。
int value[N]={25,10,20,30};//各个物品的价值。
int f[V+1]; //f[j]意味容积j时的最优解。
int zeroonepack()
{
    int i,j;
    memset(f,0,sizeof(f)); //先把f[]初始化为0。
    for(i=0;i<N;i++)   //找出容积为 j 时向背包里装物品的最优解
    {
        for(j=V;j>=weight[i];j--)  
        {
            f[j]=max(f[j],f[j-weight[i]]+value[i]); 
            cout << j << " " << f[i] << endl;
        }
    }                 //求最优解结束
    return f[V]; //输出容积为V时的最佳解(即背包装满时的最优解)
}
int main()
{
    cout << zeroonepack() << endl; //调用函数
    return 0;
}

注意:

有的题目要求“恰好装满背包”时的最优解,有的题目则并没有要求必须把背包装满。
如果是第一种问法,要求恰好装满背包,那么在初始化时除了f[0]为0,其它f[1..V ]均设为−∞,这样就可以保证最终得到的f[V ]是一种恰好装满背包的最优解。

二、完全背包

事例:

有N种物品和一个容量为V 的背包,每种物品都可装入无限次。第i种物品所占容量为v[i],价值是W[i]。求将哪些物品装入背包可使总价值最大。

思路:

  1. 可将该问题看成01背包问题。
  2. 不同点是:
    01背包是一件物品只能用一次,于是我们从体积为V开始,倒着减。
    完全背包是从第1件物品开始,只要体积不超过背包容量V就可以一直装,那么一件物品就可以用好多次。

代码:

#include <iostream>
#include <cstring>
using namespace std;
const int N=4;
const int V=5;
int weight[N]={1,2,2,3};
int value[V]={25,10,20,30};
int f[V+1];
int completepace()
{
    memset(f,0,sizeof(f));
    int i,j;
    for(i=0;i<=N;i++)
    {
        for(j=weight[i];j<=V;j++)    //从第i件物品开始放
        {
            f[j]=max(f[j],f[j-weight[i]]+value[i]);
            cout << j << " " << f[j] << endl;
        }
        return f[V];
    }
}

int main()
{
    cout << completepace() << endl;
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_41268947/article/details/79907438