基础算法——动态规划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背包问题的主要内容,如果未能解决你的问题,请参考以下文章