0/1背包问题
一个旅行者有一个最多能装m公斤的背包,现在有n个物品,重量分别是W1,W2,... , Wn 。
每件的价值分别为V1,V2, ... , Vn 。求旅行者能装入的最大总价值及其解向量。
贪心算法
总是做出在当前看来是最好的选择。
不从整体最优上加以考虑,做出局部最优解。
贪心算法不一定能得到整体最优解,但可以得到整体最优解的近似解。
CodeDemo
<span style="font-size:14px;">import java.util.*;
public class GreedyPackage {
public static void main(String[] args) {
// 输入流
Scanner sc = new Scanner(System.in);
System.out.println("请输入物品数量:" );
int n = sc.nextInt();
System.out.println("请输入物品的重量(以空格间隔):");
int[] w = new int[n];
for(int i=0;i<n;i++)
w[i] = sc.nextInt();
System.out.println("请输入物品的价值(以空格分隔)");
int[] v = new int[n];
for(int j=0;j<n;j++)
v[j] = sc.nextInt();
System.out.println("请输入背包的容量:");
int m = sc.nextInt();
// v/w
double[] r = new double[n];
for(int k=0;k<n;k++)
r[k] = (double)v[k]/(double)w[k];
// 记录 w[i] - i
Map map = new HashMap();
for(int i=0;i<n;i++)
map.put(w[i], i);
// 选择排序
int tempInt;
double tempDouble;
for(int i=0;i<n-1;i++){
for(int j=i+1;j<n;j++){
if(r[i] < r[j]){
tempDouble = r[i]; // 互换r[i]
r[i] = r[j];
r[j] = tempDouble;
tempInt = w[i]; // 互换w[i]
w[i] = w[j];
w[j] = tempInt;
tempInt = v[i]; // 互换v[i]
v[i] = v[j];
v[j] = tempInt;
}
}
}
// 加入背包
int total = 0; // 总价值
int[] x = new int[n]; // 解向量
for(int i=0;i<n;i++){
if(w[i] <= m){
m = m - w[i]; // 减重量
total += v[i]; // 加价值
x[(int)map.get(w[i])] = 1; // 获得原始w[i]对应的i
}
}
// 输出结果
System.out.println("最大总价值为:" + total);
System.out.print("解向量为:");
for(int i=0;i<n;i++)
System.out.print(x[i] + " ");
}
}</span>
测试样本
n = 4
w[i] = { 5,4,6,3 }
v[i] = { 10,40,30,50 };
c = 10
输出
最大总价值为:90
解向量为:0 1 0 1