本文为博主原创文章,未经允许禁止转载。http://blog.csdn.net/icydate/article/details/79589590
问题描述:
设有n个物体和一个背包,物体i的重量为wi ,价值为vi ,背包的容量为C.若将物体i的xi部分(1≤i≤n, 0≤xi≤1)装入背包,则具有
价值为vi xi. 目标是找到一个方案,使放入背包的物体总价值最高.
解题思路:
首先,这里的物品是可以拆分的,所以我们要尽可能的放单位价值最高的物品进去
1、先计算所有物品的单位价值
2、取价值最高者,放入背包
3、计算背包剩余空间
4、在剩下的物品中,取价值最高的,放入背包,直到背包装满,或物品装完。
例子:
物品价值{p1,p2,p3}={25,24,15};物品重量{w1,w2,w3}={18,15,10}
简单计算一下单位价值,发现{v1,v2,v3}={1.3888,1.6,1.5};
所以第二个物品装得越多,总价值越高,如下表
接下来是代码
public class GreedySelector {
public static void main(String[] args) {
int n = 3; //物品数量
float m = 20; //背包总容量
float[] p = {25,24,15}; //物品价值
float[] w = {18,15,10}; //物品重量
float[] x = {1,1,1}; //每个物品装入背包的量
test(n, m, p, w, x);
}
public static void test(int n,float m,float[] p,float[] w,float[] x){
float[] value = new float[n]; //物品单位价值
float sum = 0; //用于存放装入的总价值
for(int i = 0;i<n;i++){
value[i]=p[i]/w[i]; //将计算好的物品单位价值放入数组
}
//降序排序,将物品价值,物品重量都以单位价值从大到小排序
for(int i = 0;i < n;i++){
for(int j = i;j < n;j++){
//第一轮,将数组第一位与每一位比较,每次比较把值大的放入第一位,能保证循环结束后第一位一定是最大的。
//第二轮,就从数组第二位开始,保证第二位是剩余数中最大的,以此达到降序排列
//将物品价值,物品重量降序排序,保证之后的循环一定是单位价值高的物品先装入
if(value[i] < value[j]){
float temp = value[i];
value[i] = value[j];
value[j] = temp;
float temp2 = p[i];
p[i] = p[j];
p[j] = temp2;
float temp3 = w[i];
w[i] = w[j];
w[j] = temp3;
}
}
}
//初始化,表示所有东西都没装
for(int i = 0;i < n;i++){
x[i]=0;
}
int index = 0; //用于存放最后一个没装入的物品索引
//先将单位价值最高的物品放入书包
for(int i = 0;i < n;i++){
index = i;
if(w[i]>m){ //当当前物品重量大于背包剩余重量时结束循环
break;
}
x[i]=1; //代表全部装入
m -= w[i]; //减去已转入的物品重量
}
//可能存在最后一个物品总重量已经大于剩余重量,但能够装一部分进去的情况
if(index < n){
x[index]=m / w[index]; //计算其能装入多少
}
//计算总价值
for(int a = 0;a <= index;a++){
sum += x[a]*p[a]; //装入的比例*该物品的总价值
}
System.out.println("贪心算法所计算的总价值为:" + sum);
}
}
运行一下,结果与表格里是一样的