• 【算法设计与分析基础】21、动态规划-背包问题


    问题:

    * 对一组物品:
    * 重量为:w1,w2,w3....wn
    * 价值为:v1,v2,v3,....vn
    * 和一个可以存放重量为W的背包
    * 求这些物品装进去如何才会是最右价值的装法

    解题思路

    对于这些物品进行分类,判断第i个物品是否需要加入背包

    获取到的结果就是,放入前i个物品进入重量是j的方式是
    V[i,j] = max {V[i - 1, j], vi + V[i - 1, j - wi]} (包含和不包含第i个的问题)
    当wi超标的时候,V[i,j] = V[i - 1, j] 也就是 wi > j

    问题求解:

    解题:

    package cn.xf.algorithm.ch08DynamicProgramming;
    
    import org.junit.Test;
    
    /**
     * 动态规划,背包问题
     * 
     * 对一组物品:
     * 重量为:w1,w2,w3....wn
     * 价值为:v1,v2,v3,....vn
     * 和一个可以存放重量为W的背包
     * 求这些物品装进去如何才会是最右价值的装法
     * .
     * 
     * @版权:福富软件 版权所有 (c) 2017
     * @author xiaof
     * @version Revision 1.0.0
     * @see:
     * @创建日期:2017年8月7日
     * @功能说明:
     *
     */
    public class BackPack {
    //    解题思路:对于这些物品进行分类,判断第i个物品是否需要加入背包
    //    获取到的结果就是,放入前i个物品进入重量是j的方式是
    //    V[i,j] = max {V[i - 1, j], vi +  V[i - 1, j - wi]} (包含和不包含第i个的问题)
    //    当wi超标的时候,V[i,j] = V[i - 1, j] 也就是 wi > j
        /**
         * 
         * @param values  依次物品的价值
         * @param weight  依次物品的重量
         * @param W 背包大小
         */
        public int[][] typeBack(int values[], int weight[], int W) {
            int resultValue[][] = new int[values.length][W + 1];
            //初始化,当价值为0的时候,那么背包里面肯定没有物品
            for(int i = 0; i < W + 1; ++i) {
                resultValue[0][i] = 0;
            }
            //遍历所有的物品,并且遍历背包重量
            for(int i = 1; i < values.length; ++i) {
                //遍历所有物品,当背包大小为0的时候,那么价值结果肯定为0
                resultValue[i][0] = 0;
                for(int j = 1; j <= W; ++j) {
                    //背包大小慢慢增加
                    //当前物品i是否对应不同的背包是否放入的问题,价值是几何
                    if(j > W || j - weight[i] < 0) {
                        //当前物品重量大于背包,背包不可能包含这个物品
                        resultValue[i][j] = resultValue[i - 1][j];
                    } else {
                        resultValue[i][j] = maxValue(resultValue[i - 1][j], values[i] + resultValue[i - 1][j - weight[i]]);
                    }
                }
            }
            
            return resultValue;
        }
        
        public int maxValue(int a, int b) {
            if(a > b) {
                return a;
            } else {
                return b;
            }
        }
        
        //对背包问题实现动态规划的记忆功能,避免对部门数据的重复计算
        public int MFKTypeBack(int result[][], int values[], int weight[], int i, int j) {
            //递归就是,判断需要求的位置的值是否已经存在,如果还没求出来,那么就递归
            int value;
            if(i == 0 || j == 0) {
                //递归终止条件
                value =  result[i][j];
            } else {
                if(result[i][j] <= 0) {
                    //如果这个值还没有被获取出来
                    //判断当前物品的重量是否超标
                    if(j - weight[i] < 0) { //这个表示,如果背包中包含这个物品,去掉这个物品之后,背包中物品最少要不小于0
                        //当前物品重量大于背包,背包不可能包含这个物品
                        value = MFKTypeBack(result, values, weight, i - 1, j);
                    } else {
                        value = maxValue(MFKTypeBack(result, values, weight, i - 1, j), 
                            values[i] + MFKTypeBack(result, values, weight, i - 1, j - weight[i]));
                    }
                    result[i][j] = value;
                }
            }
            return result[i][j];
        }
        
        
        @Test
        public void test1() {
            int weight[] = {0,2, 1, 3, 2};
            int values[]= {0, 12, 10, 20, 15 }; // 价值数组
            int W = 5;
            BackPack bp = new BackPack();
            int result[][] = bp.typeBack(values, weight, W);
            for (int i = 0; i < result.length; i++) {
                for (int j = 0; j < result[0].length; j++) {
                    System.out.print(result[i][j] + "     ");
                }
                System.out.println();
            }
            int result2[][] = new int[weight.length][W + 1];
            for(int i = 0; i < weight.length; ++i) {
                for(int j = 0; j < W + 1; ++j) {
                    result2[i][j] = 0;
                }
            }
            //从第一个物品选中开始
            int valueR = bp.MFKTypeBack(result2, values, weight, 4, 5);
            System.out.println("结果值:" + valueR);
        }
        
    }
    

      

    结果:

     

  • 相关阅读:
    Java主流日志工具库
    JSON 与 String、Map、JavaBean互转
    Session超时处理
    spring cron表达式(定时器)
    Windows服务器下用IIS Rewrite组件为IIS设置伪静态方法
    JAVA导出Excel(支持多sheet)
    自己实现一个简单的线程池
    数据库
    计算机网络
    HashMap源码分析
  • 原文地址:https://www.cnblogs.com/cutter-point/p/7299865.html
Copyright © 2020-2023  润新知