用贪心算法接部分背包问题:
首先计算出每种商品单位重量vi/wi ,然后依贪心选择策略,将尽可能多的单位重量价值最大的物品全部(注意这里的全部,就是一整个装入,想0-1背包那样装)装入背包。若将这种物品装完后还有剩余空间(一般都有剩余),则选择剩余物品单位最高的物品并尽可能的多装入背包。
package 贪心算法;
import java.util.Scanner;
class goods {
int id;
float w;
int v;
public goods() {
}//空构造方法,在排序中当做temp
public goods(int id, float w, int v) {//构造方法,给属性赋值,对物品初始化,编号,重量,价值
this.id = id;
this.w = w;
this.v = v;
}
//想用比较接口,发现不行,也可能是自己不会
// @Override
// public int compareTo(goods o) {
// return (int)(this.w/this.v)-(o.w/o.v);//升序,小于则this放前面,大于则this放后面
// }
}
/*
测试用例
3
50
60 10
100 20
120 30
*/
public class 背包wenti {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
System.out.println("商品数:");
int n = in.nextInt();
System.out.println("背包容量:");
int c = in.nextInt();//当前容量
System.out.println("商品价值和重量:");
float[] w = new float[n];
int[] v = new int[n];
float[] x = new float[n];//X用来标记选择物品的多少,0~1,
for (int i = 0; i < n; i++) {
v[i] = in.nextInt();
w[i] = in.nextInt();
}
goods[] gs = new goods[n];
for (int i = 0; i < n; i++) {
gs[i] = new goods(i, w[i], v[i]);
}
knaspack(c, x, gs);
}
private static void knaspack(int c, float[] x, goods[] gs) {
sort(gs);
int i;//i用来标记选择了多少商品
int opt = 0;
int n = gs.length;
for (i = 0; i < n; i++) x[i] = 0;
for (i = 0; i < n; i++) {
if (gs[i].w <= c) {
x[gs[i].id] = 1;//空间足够,物品全选
opt += gs[i].v;
c -= gs[i].w;//加价值,减容量
} else break;//空间不足装满一整个,跳出循环
}
if (i < n) {
x[gs[i].id] = c / gs[i].w;//算出是小数,并且只可能小于1,大于等于就在上面循环中处理了
opt += x[gs[i].id] * gs[i].v;//将背包装满,价值最大化
}
System.out.println("最大装入价值:" + opt);
}
private static void sort(goods[] gs) {//按性价比(价值/体积)降序排序
for (int i = 0; i < gs.length; i++) {
float p1 = gs[i].v / gs[i].w;
for (int j = i + 1; j < gs.length; j++) {
float p2 = gs[j].v / gs[j].w;//单价
if (p1 < p2) {
goods goods = new goods();
gs[i] = goods;
gs[j] = gs[i];
gs[i] = goods;
}
}
}
}
}