本文有引用其他作者的文章,请看对应算法后的原文链接
1)贪心算法
C=150C=150, 最大承重
wi=[35,30,60,50,40,10,25]wi=[35,30,60,50,40,10,25],每个物品的重量
pi=[10,40,30,50,35,40,10]pi=[10,40,30,50,35,40,10],每个物品的价格
关键在于子问题的定义,本例,我么可以将子问题定义为,在选取某一物品(wiwi)放入背包以后,在背包容量还有C′:=C−wiC′:=C−wi的情况下,选择下一个物品放入背包。
如何选择每一次子问题的所需确定的物品呢?这正是贪心策略的选择问题了。对于本题,常见的贪婪策略有三种,
1.根据物品价值选择,每次都选价值最高的物品
[4, 2, 6, 5]-> 130(总重量),165(价值)
2.根据物品重量选择,每次都选最轻的
[6, 7, 2, 1, 5] -> 140(总重量),155(总价格)
3.根据价值密度(也即性价比),每次都选性价比最高的
性价比:[0.286, 1.333, .5, 1., .0875, 4., 1.2]
[6, 2, 7, 4, 1] -> 150(总重量),170(总价格)
该算法原文:https://blog.csdn.net/lanchunhui/article/details/49962709
2)动态规划
Java关键代码:
/*计算最优值方法
* Knapsack(数量n,背包容量c,重量列表w,价值列表v,数组M){}
* return:无
* 说明:计算并构建0-1最优值M数组
*
* i,j:循环变量
* Jmax:背包已用容量
*/
public static void Knapsack(int n,int c,int w[],int v[],int m[][]){
int i,j;
int Jmax = Min(w[n]-1,c);//找到最后物品不能存放的容量区间上限
for(i=0;i<=Jmax;i++)//最后一个物品不能存放的区间,价值设为0
m[n][i]=0;
for(i=w[n];i<=c;i++)//可以存放,填入最后一个物品价值
m[n][i]=v[n];
for(i=n-1;i>0;i--){
Jmax = Min(w[i]-1,c);//找到当前背包已用容量
for(j=0;j<=Jmax;j++)//填入背包已用容量的价值
m[i][j]=m[i+1][j];
for(j=w[i];j<=c;j++)//将原有物品的价值和加入物品后的总价值中的最大指,填入背包未用容量
m[i][j]=Max(m[i+1][j],m[i+1][j-w[i]]+v[i]);
}
m[0][c] = m[1][c];//先将原最大价值设为当前最大价值
if(c>=w[0])//如果还能装下1号物品,填入原最大价值和加入1号物品后的总价值中的最大值
m[0][c]=Max(m[0][c],m[1][c-w[1]]+v[i]);
}
/*生成最优解序列方法
* Traceback(数量n,背包容量c,重量列表w,数组M,解序列数组X){}
* return:无
*
*
* i:循环变量
* Jmax:背包已用容量
*/
public static void Traceback(int n,int c,int w[],int m[][],int x[]){
for(int i=0;i<n;i++){
if(m[i][c]==m[i+1][c])//如果当前总价值==上一轮总价值
x[i]=0; //当前物品未加入背包
else{
x[i]=1; //否则,当前物品加入背包
c-=w[i];//背包容量减去当前物品总量,供下一循环返回到添加物品时的容量
}
}
if (m[n][c]!=0)//判断最后一个物品重量是否超过背包容量
x[n] = 1;//没有超过,则被加入背包
else
x[n] = 0;//超过,则被加入背包
}
3)分支限界法
例:0/1背包问题。假设有4个物品,其重量分别为(4, 7, 5, 3),价值分别为(40, 42, 25, 12),背包容量W=10。首先,将给定物品按单位重量价值从大到小排序,结果如下:
价值上界:用贪心算法求背包问题
4*10+6*6=76
价值下界:用贪心算法求0/1背包问题(选价值最高且能够存放的物品)
40+25=65
目标函数:
通过这个函数得到的一个和待处理节点表:
待处理节点表 |
1(100) |
2(76)、3(60) |
5(70) |
6(69)、7(64) |
9(65) |
具体步骤:
(1)在根结点1,没有将任何物品装入背包,因此,背包的重量和获得的价值均为0,根据限界函数计算结点1的目标函数值为10×10=100;
(2)在结点2,将物品1装入背包,因此,背包的重量为4,获得的价值为40,目标函数值为40 + (10-4)×6=76,将结点2加入待处理结点表PT中;在结点3,没有将物品1装入背包,因此,背包的重量和获得的价值仍为0,目标函数值为10×6=60,将结点3加入表PT中;
(3)在表PT中选取目标函数值取得极大的结点2优先进行搜索;
(4)在结点4,将物品2装入背包,因此,背包的重量为11,不满足约束条件,将结点4丢弃;在结点5,没有将物品2装入背包,因此,背包的重量和获得的价值与结点2相同,目标函数值为40 + (10-4)×5=70,将结点5加入表PT中;
(5)在表PT中选取目标函数值取得极大的结点5优先进行搜索;
(6)在结点6,将物品3装入背包,因此,背包的重量为9,获得的价值为65,目标函数值为65 + (10-9)×4=69,将结点6加入表PT中;在结点7,没有将物品3装入背包,因此,背包的重量和获得的价值与结点5相同,目标函数值为40 + (10-4)×4=64,将结点6加入表PT中;
(7)在表PT中选取目标函数值取得极大的结点6优先进行搜索;
(8)在结点8,将物品4装入背包,因此,背包的重量为12,不满足约束条件,将结点8丢弃;在结点9,没有将物品4装入背包,因此,背包的重量和获得的价值与结点6相同,目标函数值为65;
(9)由于结点9是叶子结点,同时结点9的目标函数值是表PT中的极大值,所以,结点9对应的解即是问题的最优解,搜索结束。
该算法原文:http://www.cnblogs.com/FreeAquar/archive/2012/06/21/2291436.html