LEIZHANG ' s GitHub

动态规划算法

动态规划算法

1. 算法介绍

动态规划(Dynamic Programming)算法的核心思想是:将大问题划分为小问题,进行解决,从而一步步获取最优解的处理算法

其算法思想与分治法类似,与分治法不同的是,适合于动态规划求解的问题,经过分解得到的子问题往往不是独立的(下一个子阶段的求解是建立在上一个子阶段和解的基础上,进行进一步的求解)

动态规划可以通过填表的方式来逐步推进,得到最优解

2. 应用场景-背包问题

背包问题:在重量不超出的情况下,装入物品不重复的情况下,装入总价值最大!

物品 重量 价格
吉他 1 1500
音响 4 3000
电脑 3 2000

3. 算法思路

  • 每次遍历第 i 个物品,根据w[i] 与 v[i] 来确定是否需要将该物品放入背包中
  • 即对于给定的 n 个物品,设v[i]、w[i]分别为第 i 个物品的价值和重量,C为背包的容量。
  • 再令v[i] [j]表示在前 i 个物品中能够装入容量为 j 的背包中的最大价值。
v[i][0] = v[0][j] = 0

w[i] > j时: v[i][j] = v[i - 1][j]
    
j >= w时:v[i][j] = max[v[i - 1][j]]
    
    
i:商品号
j:背包容量
v[i]: i 商品的价值
w[i]: i 商品的重量
v[i][j]:表示在前 i 个物品中能够装入容量为j的背包中的最大价值
v[i - 1][j]:上一个单元格装入的最大值
v[i - 1][j - w[i]]:装入 i - 1 商品,到剩余空间 j - w[i]的最大值

4. 代码实现

package cn.imut;

public class KnapsackProblem {
    public static void main(String[] args) {
        int[] w = {1, 4, 3};                //物品的重量
        int[] val = {1500, 3000, 2000};     //物品的价值
        int m = 4;                          //背包容量
        int n = val.length;                 //物品的个数

        //v[i][j]表示前 i 个物品能够装入容量为 j 的背包的 最大价值
        int[][] v = new int[n + 1][m + 1];
        //记录放入商品的情况
        int[][] path = new int[n + 1][m + 1];

        //初始化
        for(int i = 0; i < v.length; i++) {
            v[i][0] = 0;    //将第一列设为 0
        }
        for(int j = 0; j < v.length; j++) {
            v[0][j] = 0;    //将第一行设为 0
        }

        //动态规划处理
        for (int i = 1; i < v.length; i++) {        //不处理第一行 i 从 1开始
            for(int j = 1; j < v[0].length; j++) {  //不处理第一列,j 从 1开始
                if(w[i - 1] > j) {
                    v[i][j] = v[i - 1][j];
                }else {
                    if(v[i - 1][j] < val[i - 1] + v[i - 1][j - w[i - 1]]) {
                        v[i][j] = val[i - 1] + v[i - 1][j - w[i - 1]];
                        //将情况记录到path
                        path[i][j] = 1;
                    }else {
                        v[i][j] = v[i - 1][j];
                    }
                }
            }
        }

        //输出v,查看目前情况
        for (int[] ints : v) {
            for (int anInt : ints) {
                System.out.println(anInt + " ");
            }
            System.out.println();
        }

        System.out.println("=======================");

        int i = path.length - 1;
        int j = path[0].length - 1;
        while (i > 0 && j > 0) {
            if(path[i][j] == 1) {
                System.out.printf("第%d个商品放入背包\n", i);
                j -= w[i - 1];
            }
            i--;
        }
    }
}
posted @ 2020-04-29 21:57  LEI_Z  阅读(318)  评论(0)    收藏  举报