动态规划(一)——0-1背包问题

动态规划(1)——0-1背包问题

1 题目描述

  对于一组不同重量、不可分割的物品,我们需要选择一些装入背包,在满足背包最大重量限制的前提下,背包中物品总重量的最大值是多少呢?

2 输入

  第一行是物品的个数n(1≤n≤100000),背包容量w(1≤w≤1000000);
  第二行是n个物品的重量。

3 输出

  输出最大值

4 样例输入

5 9
2 2 4 6 3

5 样例输出

9

6 求解思路

  把问题分解为多个阶段,每个阶段对应一个决策。我们记录每一个阶段可达的状态集合(去掉重复的),然后通过当前阶段的状态集合,来推导下一个阶段的状态集合,动态地往前推进。这也是动态规划这个名字的由来,你可以自己体会一下,是不是还挺形象的?

7 C++版本代码如下

#include <iostream>
#include <math.h>
#include <string.h>
using namespace std;

#define MAXNUM 100010

int dpFirst(int weight[], int n, int weightLimit){
    bool states[n][weightLimit + 1];
    memset(states, false, sizeof(states));
    // 第一行单独处理
    states[0][0] = true;
    if(weight[0] <= weightLimit)
        states[0][weight[0]] = true;

    // 动态规划状态转移
    for(int i = 1; i < n; i++){
        for(int j = 0; j < weightLimit + 1; j++)
            if(states[i - 1][j]){
                // 不装
                states[i][j + 0] = true;
                // 装
                states[i][j + weight[i]] = true;
            }
    }
    // 找出最后一个状态下的背包值
    int maxPower = 0;
    for(int i = 0; i <= weightLimit; i++)
        if(states[n - 1][i])
            maxPower = i;
    return maxPower;
}

int main()
{
    int weight[5] = {2,2,4,6,3};
    cout<<dpFirst(weight, 5, 9)<<endl;;
    return 0;
}

  因为只需要判断最后一个状态下的背包容量,所以可以使用一个数组states[weightLimit]即可解决问题,代码可优化空间复杂度如下:
  其中注意上一个二维数组的方法中数组weight的访问可能越界,所以修改为j <= weightLimit - weight[i + 1]保证了数组weight不会越界,表示“当前状态”能装下的。

int dpFirst(int weight[], int n, int weightLimit){
    bool states[weightLimit + 1];
    memset(states, false, sizeof(states));
    // 单独处理第一个状态
    states[0] = true;
    if(weight[0] <= weightLimit)
        states[weight[0]] = true;

    // 动态规划状态转移用一个数组解决
    for(int i = 1; i < n; i++){
        // 可以直接写成weightLimit - weight[i],而不是weightLimit
        // 这样可以少几个判断,并且保证了数组weight不会越界
        for(int j = 0; j <= weightLimit - weight[i]; j++){
            if(states[j])
                // 装
                states[j+ weight[i]] = true;
        }
    }

    // 找出最后一个状态下的背包值
    for(int i = weightLimit; i >= 0; i--)
        if(states[i])
            return i;
}
原文地址:https://www.cnblogs.com/flyingrun/p/13495653.html