动态规划
关于动态规划问题,入门者一般会学习背包问题(参考百度词条:背包问题),而关于背包问题,入门者一般会学习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的空间大小要和背包体积挂钩,而不是和物品数量挂钩!!!
圆满完成。

浙公网安备 33010602011771号