背包问题
1.问题描述:
有n个宝物,每个宝物有一定的重量w和价值v,而运载的容量有限,容量为m,(宝物可以分割),怎么才能使运走的宝物价值最大呢。
2.方法:每次从剩下的宝物中选出性价比最高的宝物。
3.算法设计:
①数据结构与初始化:
设计一个结构体,存储宝物的重量w和价值v,和性价比。
static class Three implements Comparable<Three> {
Three(double w, double v) {
this.w = w;
this.v = v;
this.p = this.v / this.w;
}
②按照性价比高低降序排序,用sum表示每次放入宝物后的容量,sum初始化为0.
double w;//每个宝物的重量
double v;//每个宝物的价值
double p;//性价比
@Override
public int compareTo(Three o) {
return (o.p>this.p)?1:-1 ;//倒叙 由于是double 不能采用o.p-this.p形式
}
③依次放入容器中,按照性价比从大到小,直到到达最大容量m。
Arrays.sort(s);
double sum = 0.0;//sum表示贪心记录运走宝物的价值之和
for (int i = 0; i < n; i++) {//按照排好的顺序贪心
if (m > s[i].w) {//如果宝物的重量小于毛驴剩下的承载能力
m -= s[i].w;
sum += s[i].v;
} else {//如果宝物的重量大于毛驴剩下的承载能力
sum += m * s[i].p;//部分装入
break;
}
}
特殊判断:
当放入某个宝物前,sum<=m,放入后,sum>m,如果宝物是可分割的,就将其按照余下容量分割后放入;如果不能分割,就不放入(但是这种情况只能得到最优解的近似值)。
完整代码:
package com.weikun.greedy;
import java.util.Arrays;
/**
* 创建人:Jason
* 创建时间:2020/4/18
* 描述你的类:阿里 背包问题
*/
public class B {
static class Three implements Comparable<Three> {
Three(double w, double v) {
this.w = w;
this.v = v;
this.p = this.v / this.w;
}
double w;//每个宝物的重量
double v;//每个宝物的价值
double p;//性价比
@Override
public int compareTo(Three o) {
return (o.p>this.p)?1:-1 ;//倒叙 由于是double 不能采用o.p-this.p形式
}
}
public static void main(String[] args) {
int n = 10;//n表示有n个宝物
double m = 30;//m表示毛驴的承载能力
Three[] s = new Three[]{
new Three(4, 3),
new Three(2, 8),
new Three(9, 18),
new Three(5, 6),
new Three(5, 8),
new Three(8, 20),
new Three(5, 5),
new Three(4, 6),
new Three(5, 7),
new Three(5, 15)
};
Arrays.sort(s);
double sum = 0.0;//sum表示贪心记录运走宝物的价值之和
for (int i = 0; i < n; i++) {//按照排好的顺序贪心
if (m > s[i].w) {//如果宝物的重量小于毛驴剩下的承载能力
m -= s[i].w;
sum += s[i].v;
} else {//如果宝物的重量大于毛驴剩下的承载能力
sum += m * s[i].p;//部分装入
break;
}
}
System.out.println("装入的宝物的最大价值:" + sum);
}
}