0-1背包问题

题目描述:

有 N 件物品和容量为 M 的背包,第 i 件物品的体积是 w[i],价值是 d[i],求解将哪些物品放入背包可以使价值总和最大,每种物品只有一件,可以选择放或者不放。(N<=3500 , M<=13000)

第一行有两个数据,分别是 N 和 M,接下来 N 行,分别输入每件物品的体积和价值。

样例输入

4 6
1 4
2 6
3 12
2 7

样例输出

23

看过很多大神们写的有关这个问题的解法,我来分享一种不同的解法,或者说是稍微改进了一下,即不用二维数组,有大神提到过滚动数组,原谅鄙人学识浅薄,实在转化不过来了,即用两个一维数组实现递推,至于此题涉及到的递推思想,我就不再赘述了。简单说一下,对于上例,给上面物品分别标记 A,B,C,D,思想就是当只有一个A物品时,背包容量从 1~6 的最大价值分别是4,4,4,4,4,4, 最大价值是 4 , 然后再加入一个B物品后,背包从 1~6 所能容纳的最大价值分别是 4,6,10,10,10,10,最大价值是 10,继续,三个物品,背包所能容纳的最大价值分别是4,6,12,16,18,22,最大价值是 22,再加入D物品,最大价值为 23 。状态迁移方程: F[i][j] = max(F[i-1][j],F[i-1][j-weight[i]]+value[i]);  分别代表取或不取。i-1 是上一种状态得到的结果。

poj原题链接:

http://poj.org/problem?id=3624

AC代码:

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

int N,M;

int sum(int bag[],int bag1[],int w[],int v[])
{
    int n = 1;
    for(int i = 1; i <= N; i++)
    {
        for(int j = 1; j <= M; j++)
        {
            if(n%2 == 1)
            {
                if(j < w[i])
                    bag[j] = bag1[j];
                else
                    bag[j] = max(bag1[j],bag1[j-w[i]]+v[i]);
            }
            else
            {
                if(j < w[i])
                    bag1[j] = bag[j];
                else

                    bag1[j] = max(bag[j],bag[j-w[i]]+v[i]);
            }
        }
        n++;
    }
    if(n%2 == 0)
        return bag[M];
    else
        return bag1[M];
}

int main()
{
    cin>>N>>M;
    int value[N + 1];
    int weight[N + 1];
    int bag[M+1],bag1[M+1];
    memset(bag,0,4*(M+1));
    memset(bag1,0,4*(M+1));
    memset(weight,0,4*(N+1));
    memset(value,0,4*(N+1));
    for(int i = 1; i<=N; i++)
        cin>>weight[i]>>value[i];
    cout<<sum(bag,bag1,weight,value)<<endl;
    return 0;
}
原文地址:https://www.cnblogs.com/NikkiNikita/p/9450760.html