算法笔记_019-背包问题(Java)

来源:互联网 发布:js window 添加方法 编辑:程序博客网 时间:2024/05/16 13:07

目录

1 问题描述

2 解决方案

2.1 蛮力法

 


1 问题描述

给定n个重量为w1w2w3...wn,价值为v1v2...vn的物品和一个承重为W的背包,求这些物品中最有价值的子集(PS:每一个物品要么选一次,要么不选),并且要能够装到背包。

附形象描述:就像一个小偷打算把最有价值的赃物装入他的背包一样,但如果大家不喜欢扮演小偷的角色,也可以想象为一架运输机打算把最有价值的物品运输到外地,同时这些物品的重量不能超出它的运输能力。

 


2 解决方案

2.1 蛮力法

使用蛮力法解决包含n个物品的背包问题,首先得求出这n个物品的所有子集,对于每一个物品存在两种情况:选中(在程序中用1表示),未选中(在程序中用0表示)。该n个物品的所有子集数数量为2^n。下面请看一个简单示例:

 

此处,使用一个二维数组存放所有子集,数组的每一行代表一个子集,每一列代表一个具体物品。

package com.liuzhen.chapterThree;public class Knapsack {        public int maxSumValue = 0;        //定义满足背包问题子集的最大承重所得的总价值,初始化为0    /*     * 数组A的行数为2^n,代表n个物品共有2^n个子集,列数为n。即每一行的排列为一个背包实例     * 数组weight存放每个物品的具体重量     * 数组value存放每个物品的具体价值     * n代表共有n个物品     * maxWeight表示背包最大承重量     */    public void bruteForce(int[][] A,int[] weight,int[] value,int n,int maxWeight){                for(int i = 0;i < Math.pow(2, n);i++){  //总共有2^n个子集,需要进行2^n次循环,及数组A有2^n行            int temp1 = i;            for(int j = 0;j < n;j++){    //数组A有n列,每一列代表一个物品                int temp2 = temp1%2;                A[i][j] = temp2;                temp1 = temp1/2;            }        }                printArray(A,weight,value,maxWeight);            }        //输出穷举方案的背包实例的选择物品(0代表不包含该物品,1表示包含该物品)的总重量及总价值,并输出最优实例的总价值    public void printArray(int[][] A,int[] weight,int[] value,int maxWeight){        int len1 = A.length;         //二维数组的行数        int len2 = A[0].length;      //二维数组的列数        for(int i = 0;i < len1;i++){            int tempWeight = 0;      //暂时计算当前选中背包实例物品的总重量,初始化为0            int tempSumValue = 0;    //暂时计算当前选中背包实例物品的总价值,初始化为0            for(int j = 0;j < len2;j++){                System.out.print(A[i][j]+" ");//                if(A[i][j] != 0)//                    System.out.print(" 物品"+j);                tempWeight += A[i][j]*weight[j];                tempSumValue += A[i][j]*value[j];            }            System.out.print("\t"+"总重量为:"+tempWeight);            if(tempWeight <= maxWeight)                System.out.print("\t"+"总价值为:"+tempSumValue);            else                System.out.print("\t"+"不可行(超出背包最大承重)");            if(tempWeight <= maxWeight && tempSumValue > maxSumValue)                maxSumValue = tempSumValue;            System.out.println();        }        System.out.println("穷举查找得知,最优解的总价值为:"+maxSumValue);    }        public static void main(String[] args){        Knapsack test = new Knapsack();        int[][] A = new int[16][4];        int[] weight = {7,3,4,5};        int[] value = {42,12,40,25};        test.bruteForce(A,weight,value,4,10);      //背包的承重最大为10    }    }

 

运行结果:

0 0 0 0     总重量为:0    总价值为:01 0 0 0     总重量为:7    总价值为:420 1 0 0     总重量为:3    总价值为:121 1 0 0     总重量为:10    总价值为:540 0 1 0     总重量为:4    总价值为:401 0 1 0     总重量为:11    不可行(超出背包最大承重)0 1 1 0     总重量为:7    总价值为:521 1 1 0     总重量为:14    不可行(超出背包最大承重)0 0 0 1     总重量为:5    总价值为:251 0 0 1     总重量为:12    不可行(超出背包最大承重)0 1 0 1     总重量为:8    总价值为:371 1 0 1     总重量为:15    不可行(超出背包最大承重)0 0 1 1     总重量为:9    总价值为:651 0 1 1     总重量为:16    不可行(超出背包最大承重)0 1 1 1     总重量为:12    不可行(超出背包最大承重)1 1 1 1     总重量为:19    不可行(超出背包最大承重)穷举查找得知,最优解的总价值为:65

 

0 0