经典算法详解 之 背包算法
来源:互联网 发布:阿里云服务器ping不通 编辑:程序博客网 时间:2024/06/06 18:47
如果我们用子问题定义状态来描述的话可以这样解释:
用f[i][v]表示前i件物品恰放入一个容量为v的背包可以获得的最大价值。用公式表示:
f[i][v]=max{f[i-1][v],f[i-1][v-c[i]]+w[i]}或 f[v]=max{f[v],f[v-c[i]]+w[i]}
具体的解释可以理解为将前i件物品放入容量为v的背包中,现只考虑第i件物品的策略(放或不放),那么就可以转化为一个只涉及前i-1件物品和第i件物品的问题。如果不放第i件物品,那么问题就转化为“前i-1件物品放入容量为v的背包中”,价值为f[i-1][v];如果放第i件物品,那么问题就转化为“前i-1件物品放入剩下的容量为v-c[i]的背包中”,此时能获得的最大价值就是f[i-1][v-c[i]]再加上通过放入第i件物品获得的价值w[i]。(v表示背包的最大容量,c[i]表示第i件物品的大小,w[i]表示第i件物品的价值)
算法如下:
class Fruit{private String name;private int size;private int price;public Fruit(String name,int size,int price){this.name=name;this.size=size;this.price=price;}public String getName(){return name;}public int getPrice(){return price;}public int getSize(){return size;}}public class Knapsack{public static void main(String[] args){final int MAX=8;final int MIN=1;int[] item=new int[MAX+1];int[] value=new int[MAX+1];Fruit fruits[]={new Fruit("李子",4,4500),new Fruit("苹果",5,5700),new Fruit("橘子",2,2250),new Fruit("草莓",1,1100),new Fruit("甜瓜",6,6700)};for(int i=0;i<fruits.length;i++){for(int s=fruits[i].getSize();s<=MAX;s++){//s表示现在背包的大小int p=s-fruits[i].getSize();//表示每次增加单位背包空间,背包所剩的空间int newvalue=value[p]+fruits[i].getPrice();//value[p]表示增加的背包空间可以增加的价值,fruits[i].getprice()表示原有的背包的价值if(newvalue>value[s]){//现有的价值是否大于背包为s时的价值value[s]=newvalue;item[s]=i;//将当前的水果项添加到背包的物品中}}}System.out.println("物品\t价格");for(int i=MAX;i>MIN;i=i-fruits[item[i]].getSize()){System.out.println(fruits[item[i]].getName()+"\t"+fruits[item[i]].getPrice());}System.out.println("合计\t"+value[MAX]);}}
程序运行的过程如下:
i=0时,放入李子
背包负重
1
2
3
4
5
6
7
8
s
-
-
-
4
5
6
7
8
p
-
-
-
0
1
2
3
4
value
0
0
0
4500
4500
4500
4500
9000
item
-
-
-
0
0
0
0
0
i=1时,放入苹果
背包负重
1
2
3
4
5
6
7
8
s
-
-
-
-
5
6
7
8
p
-
-
-
-
0
1
2
3
value
0
0
0
4500
5700
5700
5700
9000
item
-
-
-
0
1
1
1
0
i=2时,放入橘子
背包负重
1
2
3
4
5
6
7
8
s
-
2
3
4
5
6
7
8
p
-
0
1
2
3
4
5
6
value
0
2250
2250
4500
5700
6750
7950
9000
item
-
2
2
0
1
2
2
0
i=3时,放入草莓
背包负重
1
2
3
4
5
6
7
8
s
1
2
3
4
5
6
7
8
p
0
1
2
3
4
5
6
7
value
1100
2250
3350
4500
5700
6800
7950
9050
item
3
2
3
0
1
3
2
3
i=4时,放入甜瓜
背包负重
1
2
3
4
5
6
7
8
s
-
-
-
-
-
6
7
8
p
-
-
-
-
-
0
1
2
value
1100
2250
3350
4500
5700
6800
7950
9050
item
3
2
3
0
1
3
2
3
由最后一个表格可以知道,在背包负重8的时候,最多得到价值9050的水果,这个时候可以得到装入的水果是3号水果草莓,那么剩下的(8-1=7)个大小空间,可以知到为2号水果也就是橘子,同理下一步可以知道放入的水果是1号水果苹果。此时获得的最优解的价值就是9050,放入的水果是草莓、橘子和苹果。
到此,我们的背包问题已经解决,要了解上述算法,需要读者分析出背包算法中的每一步都做了什么操作,这一点可以通过上述的表格看出,希望本文对读者理解背包算法有所帮助!
- 经典算法详解 之 背包算法
- 经典算法详解 之 背包算法
- 经典算法详解 之 背包算法
- 经典算法之背包问题
- 经典算法之背包问题
- 经典算法之背包问题
- 经典算法之背包问题
- 经典算法之0-1背包问题
- 经典算法之—背包问题
- 经典算法之背包问题(0-1背包)
- 经典算法详解 之 递归算法
- 递归算法学习系列之经典背包问题
- 递归算法学习系列之经典背包问题
- 递归算法学习系列之经典背包问题
- 经典算法9:回溯法之0--1背包问题
- 递归算法学习系列之经典背包问题
- 数据结构经典算法学习之01背包问题
- 数据结构经典算法学习之完全背包问题
- project euler problem 10:Summation of primes
- Working Practice-设置免打扰时间
- FileReader详解与实例---读取并显示图像文件
- 基于私有化构造器与析构器的单件模式(singleton) 实现及注释
- 批处理抠图(透明图)
- 经典算法详解 之 背包算法
- svn git
- SDL Render 之OSD RTF 和TTF
- HTML5中微数据在搜索引擎中的使用举例
- UVa 408 Uniform Generator (最大公约数&证明)
- 开篇
- Scribe+HDFS日志收集系统安装方法
- fastboot命令
- MongoDB学习 (六):查询