题目描述
-
有n个物体,第i个物体的重量为wi,价值为vi。在总重量不超过C的情况下让总价值尽量高。每一个物体都可以只取走一部分,价值和重量按比例计算。
求最大总价值
注意:每个物体可以只拿一部分,因此一定可以让总重量恰好为C。 -
尽可能能拿单价最高的,比如黄金,相同重量情况下价值最高,从大到小选 价值/重量高的,前面的物品全拿,最后一件根据重量拿部分
代码
public static void main(String[] args) {
Scanner scanner=new Scanner(System.in);
int n=scanner.nextInt();
Goods[] goods=new Goods[n];
for (int i = 0; i < n; i++) {
goods[i]=new Goods(scanner.nextDouble(), scanner.nextDouble());
}
double C=scanner.nextDouble();
solve(goods,C);
}
private static void solve(Goods[] goods,double C) {
double curWeight=0;
double curValue=0;
Arrays.sort(goods);
System.out.println(Arrays.toString(goods));
for (int i = goods.length-1; i >= 0; i--) {
if (curWeight<C) {
if (curWeight+goods[i].wi<=C) {
curValue+=goods[i].vi;
curWeight+=goods[i].wi;
}else {
double interval=C-curWeight;
curWeight=C;
curValue+=goods[i].unitValue*interval;
}
}else {
System.out.println(curValue);
}
}
}
private static class Goods implements Comparable<Goods> {
double wi;
double vi;
double unitValue;
public Goods(double wi, double vi) {
super();
this.wi = wi;
this.vi = vi;
this.unitValue = getUnitValue(wi, vi);
}
@Override
public String toString() {
return "Goods [wi=" + wi + ", vi=" + vi + ", unitValue=" + unitValue + "]";
}
private double getUnitValue(double wi,double vi) {
return vi/wi;
}
//注意不能直接使用 return (int)(this.unitValue-o.unitValue)会丢失精度,(0,1)范围不准确
@Override
public int compareTo(Goods o) {
if (this.unitValue-o.unitValue<=0) {
return -1;
}else {
return 1;
}
}
}