算法与数据结构 - 0/1背包问题
2016-04-10 10:38
309 查看
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
;
for(int i=0;i<n;i++)
w[i] = sc.nextInt();
System.out.println("请输入物品的价值(以空格分隔)");
int[] v = new int
;
for(int j=0;j<n;j++)
v[j] = sc.nextInt();
System.out.println("请输入背包的容量:");
int m = sc.nextInt();
// v/w
double[] r = new double
;
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
; // 解向量
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
一个旅行者有一个最多能装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
;
for(int i=0;i<n;i++)
w[i] = sc.nextInt();
System.out.println("请输入物品的价值(以空格分隔)");
int[] v = new int
;
for(int j=0;j<n;j++)
v[j] = sc.nextInt();
System.out.println("请输入背包的容量:");
int m = sc.nextInt();
// v/w
double[] r = new double
;
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
; // 解向量
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
相关文章推荐
- 实现由双亲节点存储的树转化为二叉树的遍历算法实现
- 数据结构-线性表
- IOS开发之旅-IOS常用数据结构NSArray、NSMutableArray、NSDictionary、NSMutableDictionary介绍
- 数据结构综合
- 数据结构(20)栈与递归
- 树-Invert Binary Tree(翻转二叉树)
- 数据结构之串通配符匹配
- 一个数组实现两个栈
- 数据结构学习笔记(六)堆-优先队列
- 数据结构课程上机实验题(三)
- C#中常用容器的使用与底层数据结构
- 数据结构顺序表的代码实现
- 合并果子
- 木板
- 【Java数据结构】Hashmap、Hashtable、ConcurrentHashMap源码阅读笔记
- 初级线段树 POJ3264
- codeforces 555c 数据结构(map 的使用)
- 数据结构与算法08 之堆
- 过河问题-狼羊人菜
- 数据结构第三章课后题