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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章