01背包问题的其他算法

上一篇博文讲的是根据动态规划来解决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。

猜你喜欢

转载自blog.csdn.net/qq_16403141/article/details/79495339
今日推荐