动态规划算法求解0-1背包问题
摘 要(宋体四号)
本文主要阐述了基于MATLAB的0-1背包问题动态规划的求解。
0-1背包问题(Knapsack Problem,简称KP问题)是一个经典的组合优化问题,具有广泛的实际应用背景,以及在理论研究领域也有其相当的代表性。KP问题的求解,在生活中多有应用,如货源分配、轮船装载、项目选择等等都有它的身影。并且它还常常作为其他相对复杂的组合问题的一个特殊解,但当问题规模过大时,如果想要得到最优解是极其困难的,因此对大规模的0-1背包问题的研究无论是在理论研究领域还是实际应用背景都有其重要的意义。
动态规划算法是五种常用的算法之一,通常用于求解最优子结构问题。动态规划的思想和分治法相似,将一个规模较大的问题分解成规模相对足够小的子问题,再对子问题的求解,然后由这些子问题的解得到原问题的解。同分治法相比,动态规划算法的优势在于将每一个子问题计算得到的解都保存起来,用到的时候直接调用,这相对分治法来说就节省了大量重复计算时间。由于我们可以用一个表来记录所有已解子问题的答案,需要用到的时候直接调用,所以动态规划法又叫“填表法”。具体的动态规划算法有多种,但他们都具有相同的填表格式。
关键词:KP问题,0-1背包问题,动态规划,最优解,背包问题,MATLAB,基于MATLAB的0-1背包问题动态规划的求解
一.问题重述(宋体四号)
给定一个容量为C的背包和n个物品,其中物品i的体积为v[i],价值为w[i](i=1,2,3,…n),要从这n个物品中挑选出若干件放入背包,每个物品只能挑选一次,使得放入物品的总体积不超过C,而价值达到最大,并找出一种添放物品的方案。
二.模型假设(宋体四号)
0-1背包问题的为:设为一个二进制量,表示将物品i放入背包,表示物品不装入背包,即:
且
三.符号说明(宋体四号)
C:背包的容量
V:物品的体积
W:物品的价值
n:物品的数量
f:用于状态交换的矩阵
t:用于输入物品是否装入背包
四.问题分析(宋体四号)
对于0-1背包问题,每个物品都只有两种选择,装入或者不装入两种,可以用一个二维数组f[i][j]表示物品是否装入背包。我们要做的是找出可以放入背包的物品使得背包内的价值最为,利用递归思想,对于第i个物品,我们可以拿这个物品的体积同背包内剩余的体积相比较,如果背包内剩余的容量大于物品的体积,那么这个物品就可以装入背包,这时我们只要判断装入这个物品后和装入这个物品前的价值哪一个更大,就可以通过这种递归的方式球的背包能装入的最大价值。此问题的递归公式为:f[i][j]=max{f[i-1][j],f[i-1][j-v[i]]+w[i]}
五.模型建立与求解(宋体四号)
我们知道,动态规划算法又叫填表法,填表的顺序为自底向上,自左向右,于是我们首先确定第n个物品是否可以被装入背包:
if v(n)<=j
f(n,j)=w(n) ;
else
f(n,j)=0;
在通过递归公式
f[i][j]=max{f[i+1][j],f[i+1][j-v[i]]+w[i]}
逐个求解出接下来的解,最后将这些局部最优解填入表格中:
由表格中的数据我们不难发现能够装入背包的最大价值,那么,接下来我们根据这个表求解出这个最大价值是由哪集中物品装入而得到的:
%3、找出装入背包的所有物品
j=c;
for i=1:n-1
if f(i,j)==f(i+1,j)
t(i)=0;
else
t(i)=1;
j=j-v(i);
end
end
if f(n,j)==0
t(n)=0;
else
t(n)=1;
end
t
于是我们就可以得到这个最优解的“路径”:
六.模型的评价与推广(宋体四号)
不得不说KP问题是一个经典的动态规划模型,它既简单形象容易理解,又在某种程度上揭示动态规划的本质。有多种方法可以处理它,比如分支限界法、回溯法、贪心算法等等都可以对其进行求解,
七.参考文献(宋体五号)
八.附件(宋体五号)
基于MATLAB的0-1背包问题的动态规划求解源代码:
c=15; % 定义背包的最大容量
v= [2 3 6 47]; % 定义各个物品的体积
w= [10 5 816 9]; % 定义各个物品对应的价值
n=length(v); % n为物品的数量
f=[]; %定义一个用于状态交换的矩阵
t=[]; %用于输出物品是否装入背包的状态
%1、判断第一个物品放或不放
for j=1:15
if v(n)<=j
f(n,j)=w(n) ;
else
f(n,j)=0;
end
end
%2、判断下一个物品是否装入。引用递归公式f[i][i]=max{f[i-1][j],f[i-1][j-v[i]]+w[i]}
fori=n-1:-1:1
for j=1:15
if j<=v(i)
f(i,j)=f(i+1,j);
else
f(i,j)=max{f(i+1,j),f(i+1,j-v(i))+w(i)}
end
end
end
end
f
%3、找出装入背包的所有物品
j=c;
fori=1:n-1
if f(i,j)==f(i+1,j)
t(i)=0;
else
t(i)=1;
j=j-v(i);
end
end
iff(n,j)==0
t(n)=0;
else
t(n)=1;
end
t
Undefinedvariable “max” or class “max”.
>>c=15; % 定义背包的最大容量
v= [2 3 6 47]; % 定义各个物品的体积
w= [10 5 816 9]; % 定义各个物品对应的价值
n=length(v); % n为物品的数量
f=[]; %定义一个用于状态交换的矩阵
t=[]; %用于输出物品是否装入背包的状态
%1、判断第一个物品放或不放
for j=1:15
if v(n)<=j
f(n,j)=w(n) ;
else
f(n,j)=0;
end
end
%2、判断下一个物品是否装入。引用递归公式f[i][i]=max{f[i-1][j],f[i-1][j-v[i]]+w[i]}
fori=n-1:-1:1
for j=1:15
if j<=v(i)
f(i,j)=f(i+1,j);
else
iff(i+1,j)>f(i+1,j-v(i))+w(i)
f(i,j)=f(i+1,j);
else
f(i,j)=f(i+1,j-v(i))+w(i);
end
end
end
end
f
%3、找出装入背包的所有物品
j=c;
fori=1:n-1
if f(i,j)==f(i+1,j)
t(i)=0;
else
t(i)=1;
j=j-v(i);
end
end
iff(n,j)==0
t(n)=0;
else
t(n)=1;
end
t
针对动态规划填表为:
装入背包的最优子序列为: