动态规划

  关于动态规划问题,入门者一般会学习背包问题(参考百度词条:背包问题),而关于背包问题,入门者一般会学习0-1背包问题。所谓0-1背包问题,指的是物品可以选择不放或者放入,也就是每个物品最多放入一次。现在我们来通过介绍0-1背包问题了解动态规划的算法思想。

  在谈背包问题之前,我们先来给出如下定义。

  (1)属性:用于描述实体的一个名称。通常拥有一个值,组成键值对。一个实体可以有多个属性。

  (2)状态:由所关注的属性组成的集合。

  (3)转移:需要满足转移条件后,由一个旧的状态扩展转移出一个新的状态。

  在接下来关于动态规划的文章中,我们都将不断地使用以上三个定义。

  0-1背包问题模板如下:给定n(1 ≤ n ≤ 4000)件物品以及体积为v(1 ≤ v ≤ 10000)的背包,每件物品具有价值、体积两个属性,问如何合理选择物品,使得在不超过背包体积v的情况下,背包中的物品价值和最大。

  在0-1背包问题中,实体是物品,属性是物品的价值、重量等,状态是物品的价值、重量,转移条件是新状态的价值大于旧状态的价值。我们使用一个一维数组value来记录价值,例如value[i]表示在背包体积为i时的最大价值。下面给出代码实现:

  

#include <iostream>
#include <cstdio>
using namespace std;
const int MAXN = 4001;
const int MAXV = 10001;

struct BOX {
    int v;
    int w;
};

BOX box[MAXN];
int value[MAXV];
int n, w;

int max(int a, int b) {
    return a < b ? b : a;
}

int main() {
    scanf("%d%d", &n, &w);
    for(int i = 1; i <= n; i++) {
        scanf("%d%d", &box[i].w, &box[i].v);
    }
    for(int i = 1; i <= n; i++) {
        for(int j = w; j >= box[i].w; j--) {
            value[j] = max(value[j], value[j - box[i].w] + box[i].v);
        }
    }

    printf("%d", value[w]);
    return 0;
}

  需要指出的是,由于物品所占的体积都是整数,因此我们将背包体积的粒度设为1,当物品体积更小时,我们需要将粒度更加细化,当物品体积更大时,我们需要将粒度相应加大。

  特别值得注意的是,数组value的空间大小要和背包体积挂钩,而不是和物品数量挂钩!!!

 

 

 

 

  圆满完成。

posted @ 2018-08-23 10:28  potato226  阅读(121)  评论(0)    收藏  举报