上一篇博文讲的是根据动态规划来解决01背包问题,下面使用其他的几种算法来继续解决01背包问题
方法一:遍历法
解题思路:将所有组合的情况遍历一遍,为了方便,将每种组合对应一个二进制数,例如:某个背包问题中有abcde五种物品,那么00001代表只放入了a,10001代表放入了a物品和e物品。则一共有2^5=32种情况,求出每种情况下的背包总价值,记录下背包总价值最大的情况,即为最后结果。
思路说明:这种方法肯定不是很好的解决办法,但是可以解决01背包问题
代码如下:
import java.util.ArrayList;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int N = sc.nextInt();
int W = sc.nextInt();
ArrayList<String> list = new ArrayList<String>();
sc.nextLine();
for (int i = 0; i < N+1; i++) {
if(i==0)continue;
list.add(sc.nextLine().toString());
}
// 得到所有的二进制数
String[] strs = new String[(int)Math.pow(2,list.size())];
for (int i = 0; i < strs.length; i++) {
String t = Integer.toBinaryString(i);
int l = t.length();
// 保证长度为N
for(int j = l;j<N;j++){
t = "0"+t;
}
strs[i] = t;
}
int maxValue = 0;
for (int i = 0; i < strs.length; i++) {
int weight = 0;
int value = 0;
for (int j = 0; j < strs[i].length(); j++) {
// 若为1,表明该物品被选择,则加入背包
if(strs[i].charAt(j) == '1'){
String[] st = list.get(j).split(" ");
weight += Integer.parseInt(st[0]);
value += Integer.parseInt(st[1]);
}
}
// 若该方案的总体积超过背包体积,则放弃该方案
if(weight>W){
continue;
}else{
// 若该方案没有超过背包体积,则为可行方案,再判断是否为最大价值
if(value>maxValue){
maxValue = value;
}
}
}
System.out.println(maxValue);
}
}
测试如下:
代码优化
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int N = sc.nextInt();
int W = sc.nextInt();
sc.nextLine();
String[] str = new String[N];
for (int i = 0; i < N; i++) {
str[i] = sc.nextLine();
}
int maxValue = 0;
for (int i = 0; i < (int)Math.pow(2,N); i++) {
String t = Integer.toBinaryString(i);
int weight = 0;
int value = 0;
for (int j = 0; j < t.length(); j++) {
if(t.charAt(j) == '1'){
String[] st = str[N-t.length()+j].split(" ");
weight += Integer.parseInt(st[0]);
value += Integer.parseInt(st[1]);
}
}
if(weight<=W && value>maxValue) maxValue = value;
}
System.out.println(maxValue);
}
}
方法二:贪心算法
什么是贪心算法?
贪心算法并不是一个具体的算法,而是一种算法的思想,或者说是一种解决问题的思路
贪心算法,顾名思义,是一种很“贪”的算法,它的整体步骤,可以归纳为:
1.将目标问题分解成多个小问题或者多个步骤
2.在每个小问题或者步骤中,执行某种最优化策略,得到局部最优解
3.每个小问题或者步骤的最优解,组合得到全局的最优化解,不回溯处理
贪心算法解决什么问题?
解决求最优的问题,即此问题的组中目标是得到一个最优解。比如:最短路径,背包问题的最大价值等。
回到本题,本题的解题思路如下:
解题思路:根据物品的value/weight即单位重量的价值,将所有物品排序又大到小排列,性价比高的拍到最前,然后按照顺序依次放入背包,知道背包再放不下下一个物品停止。
按照这种策略,执行贪心算法求解01背包问题得到的解并不一定是最优解。下面用一个例子来说明:
输入:
3 116
100 20
14 18
10 15
可选物品有3个,体积分别为100,14,10,价值分别为20,18,15,在背包体积为116的情况下求最大价值?
体积 | 价值 | 价值/体积 |
---|---|---|
100 | 20 | 0.2 |
14 | 18 | 1.3 |
10 | 15 | 1.5 |
按照价值/体积比值大小排序,为
体积 | 价值 |
---|---|
10 | 15 |
14 | 18 |
100 | 20 |
在背包体积为116的情况下,贪心算法会选择(10,15)和(100,20),求出的最大价值为35,然后实际上的最大价值是38。