基础算法——动态规划0/1背包问题

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了基础算法——动态规划0/1背包问题相关的知识,希望对你有一定的参考价值。

  首先,对于动态规划,我来做一个简短的介绍,相信各位都看得懂。动态规划(dynamic programming)是运筹学的一个分支,是求解决策过程(decision process)最优化的数学方法。先给一道最简单的例题(小学奥数水平):

技术分享

 

技术分享

这就是一个模拟的动态规划法!

 

 

好了,现在开始认识一下最简单的动态规划实例:0/1背包

【问题描述】有一位旅行者要出远门,到商店里去筹备东西。在商店里,摆放了n样物品,每种物品有各自的体积,但是每种物品只有一件。这个旅行家有一个限制装V个体积的物品的背包,但是这个旅行家比较有钱,想买贵的东西。请编程求出:将哪些物品装入背包可使这些物品的费用总和不超过背包体积V,且价值总和最大。

乍一看到,感觉直接模拟暴力即可。但是,当数据量非常大的时候,这种方法就不显得十分的管用了。于是,我们打算用多的空间来换时间。

设数组dp[i,j]表示前i种物品装在体积为j的背包里所能获得的最大价值。存每件物品体积的数组为c,价值的数组为w

那么可以列出一个状态转移方程为:dp[i,j]:=max{dp[i-1,j],dp[i-1,v-c[i]+w[i]}。

所以稍作枚举即可。其实有点类似于记忆化搜索。

【参考程序】

 1 var
 2   c,p:  array[1..1000] of longint;
 3   i,j:  longint;
 4   f:    array[1..1000,1..1000] of longint;
 5   n,m,x:longint;
 6 Function max(a,b:integer):longint;
 7 begin
 8   if a>b then max:=a 
 9     else max:=b;
10 end;
11 
12 BEGIN
13   readln(n,m);
14   for i:=1 to n do
15   readln(c[i],p[i]);
16   for i:=1 to n do
17     for j:=1 to m do
18       if j>=c[i] then f[i,j]:=max(f[i-1,j],f[i-1,j-c[i]]+p[i])
19         else  f[i,j]:=f[i-1,j];
20   writeln(f[n,m]);
21 END.

其实,在空间上还是可以进一步优化的,如下:注意第二次循环是downto

 1 var a:array[0..100000]of longint;
 2 v,p,w,c:array[0..100]of longint;
 3 n,m,i,j:longint;
 4 begin
 5   readln(m,n);{m代表可供选择的物品数量,n包的体积}
 6   for i:=1 to m do
 7     read(v[i],w[i]); {v[i],w[i]分别代表第i件物品的体积和价值}
 8   for i:=1 to m do
 9   for j:=n downto v[i] do {从放入第一件物品到第i件物品时体积的变化}
10     if a[j]<a[j-v[i]]+w[i] 
11       then a[j]:=a[j-v[i]]+w[i];{比较放入j-1件物品和放入j件物品时价值谁大}
12    writeln(a[n]);
13 end.

 

以上是关于基础算法——动态规划0/1背包问题的主要内容,如果未能解决你的问题,请参考以下文章

动态规划算法实现部分——0/1背包问题

求动态规划0-1背包算法解释

图解算法-怎么用动态规划解决0-1背包问题

动态规划-多重背包问题

动态规划算法之0-1背包问题

动态规划算法之0-1背包问题