• 动态规划0-1背包问题


    最近看了一些简单的动态规划方面的例题 在学习的过程中发现 有的问题虽然不难 但是第一次看还是会有些问题

    所以把自己弄0-1背包的问题拿出来给大家分享 不喜勿喷 网上资源特别多

    讲解什么的就算了 其他人画的图都不错

    递推关系

        设所给0-1背包问题的最优值为m(ij),即m(ij)是背包容量为j,可选择物品为ii+1n0-1背包问题的最优值。由0-1背包问题的最优子结构性质,可以建立计算m(ij)的递归式:


         上式此时背包容量为j,可选择物品为i。此时在对xi作出决策之后,问题处于两种状态之一:
        (1)
    背包剩余容量是j,没产生任何效益;
        (2)
    剩余容量j-wi,效益值增长了vi 

     我写的代码 看完看有没有启发

    package org.bq.dp;
    
    /**
     * 0-1背包问题
     * 
     * @author 白强原创
     * @version 1.0
     */
    public class OneZero {
        // 最大背包容量
        private static final int M = 10;
        // 物品数量
        private static final int N = 3;
        // 物品重量数组 给它数组前面加一个0项是为了更好的表达这种关系 比方从一个到全部物品的时候i=2的使用w[i]=4避免减1使用w[i-1]麻烦
        private static final int[] w = { 0, 3, 4, 5 };
        // 物品价值数组
        private static final int[] v = { 0, 4, 5, 6 };
    
        public static void main(String[] args) {
            // 首先我们应该定义一个数组来记录选择的表 由于零的存在我应该吧他定义的大一些
            int[][] select = new int[N + 1][M + 1];
            int result = knapsack(select);
            System.out.println("The max value is : " + result);
            int leftSpace = M;
            // 输出所选择的物品列表:
            for (int i = N; i >= 1; i--) {
                if (leftSpace >= w[i]) {
                    // 如何确定物品被选 只需要从价值表得到
                    // 它的价值和剩余物品容量对应的价值-价值表中上排的剩余物品容量减去本物品的重量的价值==当前物品的价值
                    if ((select[i][leftSpace] - select[i - 1][leftSpace - w[i]] == v[i])) {
                        System.out.println("物品 " + i + " 重量为: " + w[i] + " 价值为: "
                                + w[i] + " is selected!");
                        // 如果第i个物品被选择,那么背包剩余容量将减去第i个物品的重量
                        leftSpace = leftSpace - w[i];
                    }
                }
            }
        }
    
        /**
         * 这是程序的算法实现
         * 
         * @param select是一个记录价值的数组它的下标
         *            [i][j] i代表当前放入物品从1到N j代表当前背包容量从1到M
         * @return 最大价值
         */
        public static int knapsack(int[][] select) {
            // 当前放入物品为零很明显它的价值全是零
            for (int j = 1; j <= M; ++j)
                select[0][j] = 0;
            // 基本算法思想上在装入一个或多个物品的时候让背包容量从1到最大 再看每一次的情况 首先能不能装 能装再看价值比较
            for (int i = 1; i <= N; ++i) {
                // 只要select[i][j] j=0即背包容量为0时,最大价值肯定为0
                select[i][0] = 0;
                // 背包容量j从小到大一直往上走直到M
                for (int j = 1; j <= M; ++j) {
                    // 当前物品i的重量小于等于背包容量j,进行选择
                    if (w[i] <= j) {
                        /*
                         * 如果本物品的价值加上背包还能放物品的价值(如何得到 剩余物品重量=当前背包容量-当前物品,
                         * 得到剩余物品的重量后在上排查询得到剩余物品的价值) 如果大于上排的值则放入
                         */
                        if ((v[i] + select[i - 1][j - w[i]]) > select[i - 1][j])
                            select[i][j] = v[i] + select[i - 1][j - w[i]];
                        else
                            // 直接使用上排的值
                            select[i][j] = select[i - 1][j];
                    } else {
                        // 当前物品还不能放入 所以还得使用上排的结果
                        select[i][j] = select[i - 1][j];
                    }
                }
            }
    
            return select[N][M];
    
        }
    }

    输出结果如下

    看一个表格我画的 表示了这个放入的过程 可以更好看出变换

    编号

    0

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    0

    0

    0

    0

    0

    0

    0

    0

    0

    0

    0

    0

    1

    0

    0

    0

    4

    4

    4

    4

    4

    4

    4

    4

    2

    0

    0

    0

    4

    5

    5

    5

    9

    9

    9

    9

    3

    0

    0

    0

    4

    5

    6

    6

    9

    10

    11

    11

    重量w = { 0, 3, 4, 5 };价值v = { 0, 4, 5, 6 }; 

  • 相关阅读:
    vim
    Linux 软链接和硬链接
    常用命令
    linux 二级目录结构
    关于bash shell的理解
    虚拟机网络模式
    安装虚拟机
    date 命令
    使用3种协议搭建yum仓库
    ubuntu update时发生错误
  • 原文地址:https://www.cnblogs.com/bq12345/p/3750682.html
Copyright © 2020-2023  润新知