01背包问题穷举法,暴力破解法(穷举法)递归

穷举法解决01背包利用暴力破解法(穷举法)

问题描述:给定n个重量为{w1, w2, … ,wn}、价值为{v1, v2, … ,vn}的物品和一个容量为C的背包,求这些物品中的一个最有价值的子集,且要能够装到背包中。

包的总容量15kg

物品情况

物品编号价值重量
14$12kg
22$2kg
32$1kg
41$1kg
510$4kg

思路:

  • 利用递归进行遍历求出各个的可能性
  • 将遍历出的结果存入int[] back = new int[N],进行缓存
  • 没存入一个back[]数组,进行遍历,将符合的题目要求allWigth[总的重量]<=15的,存入到Map<String, Integer>中
  • String表示背包情况. Integer表示总价值
  • 在存入的Map<String, Integer>的所有数据中,遍历出最大的Integer,也就是最大的价值
  • 根据Integer值,遍历出对应的String,就是背包的情况
代码

利用递归求出所有的背包情况

public class GiveBack {
     //	定义一个int数组
	int array[]=new int[1000]; 
	int N=5;
    //n为当前层数
	//求n的子集
	public  void giveback(int n){
		if(n>=N){
			for (int i = 0; i <N; i++) {
				System.out.print(array[i]);
			}
			System.out.println();
			return;
		}
		array[n]=0;
		giveback(n+1);
		array[n]=1;
		giveback(n+1);
		return;
	}
	public static void main(String[] args) {
		GiveBack giveback=new GiveBack();
		giveback.giveback(0);
	}
}

结果

所有背包情况

00000	00001	00010	00011	00100	00101	00110	00111	01000	01001	01010	01011	01100	01101	01110	01111	10000	10001	10010	10011	10100	10101	10110	10111	11000	11001	11010	11011	11100	11101	11110	11111	

最终代码

package school;

import java.util.*;

public class GiveBack3 {
    //	定义一个int数组
    int array[] = new int[1000];
    int N = 5;
    int[] value = {4, 2, 2, 1, 10};//价格
    int[] wight = {12, 2, 1, 1, 4};//体积
    int[] back = new int[N];//用来缓存所便利的可能存在的背包
    int all = 0;  //总的价值
    int allWigth = 0;//总的重量
    int count = 0;//标记遍历的次数
    Map<String, Integer> map = new HashMap<>();

    public void giveback(int n) {
        if (n >= N) {
            all = 0;//每次遍历一个循环后要置零,防止对后的影响
            allWigth = 0;
            count = 0;
            for (int i = 0; i < N; i++) {
                back[i] = array[i];
                //遍历back数组 ,所存放的背包 00100  1表示已经由背包,0表示没有
                if (back[i] == 1) {
                    all += value[i];
                    allWigth += wight[i];
                    count++;//标记遍历的次数
                } else {
                    count++;
                }
                //当遍历的次数为5和所存放的总重量小于等于15 放入Map中
                if (count == 5 && allWigth <= 15) {
                    map.put(Arrays.toString(back), all);
                }
            }
            return;
        }
        //运用递归进行调用
        array[n] = 0;
        giveback(n + 1);
        array[n] = 1;
        giveback(n + 1);
        return;
    }

    /**
     * @param map   遍历存入输入的图
     * @param value 重量
     * @return 返回value所对应的kye值
     */
    private <K, V> K getKeyByLoop(Map<K, V> map, V value) {
        for (Map.Entry<K, V> entry : map.entrySet()) {
            if (Objects.equals(entry.getValue(), value)) {
                return entry.getKey();
            }
        }
        return null;
    }

    public static void main(String[] args) {
        GiveBack3 giveback = new GiveBack3();
        giveback.giveback(0);
        //通过迭代遍历values
        Collection<Integer> values = giveback.map.values();
        Iterator<Integer> iterator = values.iterator();
        Integer temp = 0;
        while (iterator.hasNext()) {
            Integer integer = iterator.next();
            //遍历最大的values,并且赋值给temp
            if (integer > temp) {
                temp = integer;
            }
        }
        System.out.print("最大的价格\t");
        System.out.println(temp + "\t");
        //通过values值    利用getKeyByLoop函数遍历出对应的key值,也就是符合题意的而背包
        System.out.print("所选符合题意的背包\t");
        System.out.println(giveback.getKeyByLoop(giveback.map, temp));
    }
}

输出

最大的价格	15	
所选符合题意的背包	[0, 1, 1, 1, 1]

中间符合标准的,能放入背包的情况

{[0, 0, 0, 1, 0]=1, [0, 0, 0, 1, 1]=11, [0, 0, 1, 1, 0]=3, [0, 1, 0, 1, 0]=3, [1, 1, 0, 1, 0]=7, [0, 1, 1, 0, 1]=14, [0, 1, 1, 1, 0]=5, [0, 1, 0, 1, 1]=13, [0, 1, 1, 1, 1]=15, [0, 1, 0, 0, 1]=12, [0, 1, 0, 0, 0]=2, [0, 1, 1, 0, 0]=4, [0, 0, 1, 1, 1]=13, [1, 0, 0, 1, 0]=5, [1, 0, 1, 1, 0]=7, [0, 0, 0, 0, 0]=0, [1, 1, 0, 0, 0]=6, [1, 1, 1, 0, 0]=8, [0, 0, 1, 0, 1]=12, [0, 0, 1, 0, 0]=2, [0, 0, 0, 0, 1]=10, [1, 0, 1, 0, 0]=6, [1, 0, 0, 0, 0]=4}
  • 6
    点赞
  • 46
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值