初识动态规划

作者: TomGui | 来源:发表于2020-07-18 16:07 被阅读0次

    0-1 背包问题

    备忘录

    private int maxW = Integer.MIN_VALUE; // 结果放到maxW中
    private int[] weight = {2,2,4,6,3};  // 物品重量
    private int n = 5; // 物品个数
    private int w = 9; // 背包承受的最大重量
    private boolean[][] mem = new boolean[5][10]; // 备忘录,默认值false
    public void f(int i, int cw) { // 调用f(0, 0)
      if (cw == w || i == n) { // cw==w表示装满了,i==n表示物品都考察完了
        if (cw > maxW) maxW = cw;
        return;
      }
      if (mem[i][cw]) return; // 重复状态
      mem[i][cw] = true; // 记录(i, cw)这个状态
      f(i+1, cw); // 选择不装第i个物品
      if (cw + weight[i] <= w) {
        f(i+1,cw + weight[i]); // 选择装第i个物品
      }
    }
    

    动态规划-二维数组

    weight:物品重量,n:物品个数,w:背包可承载重量
    public int knapsack(int[] weight, int n, int w) {
      boolean[][] states = new boolean[n][w+1]; // 默认值false
      states[0][0] = true;  // 第一行的数据要特殊处理,可以利用哨兵优化
      if (weight[0] <= w) {
        states[0][weight[0]] = true;
      }
      for (int i = 1; i < n; ++i) { // 动态规划状态转移
        for (int j = 0; j <= w; ++j) {// 不把第i个物品放入背包
          if (states[i-1][j] == true) states[i][j] = states[i-1][j];
        }
        for (int j = 0; j <= w-weight[i]; ++j) {//把第i个物品放入背包
          if (states[i-1][j]==true) states[i][j+weight[i]] = true;
        }
      }
      for (int i = w; i >= 0; --i) { // 输出结果
        if (states[n-1][i] == true) return i;
      }
      return 0;
    }
    

    动态规划-一维数组

    public static int knapsack2(int[] items, int n, int w) {
      boolean[] states = new boolean[w+1]; // 默认值false
      states[0] = true;  // 第一行的数据要特殊处理,可以利用哨兵优化
      if (items[0] <= w) {
        states[items[0]] = true;
      }
      for (int i = 1; i < n; ++i) { // 动态规划
        for (int j = w-items[i]; j >= 0; --j) {//把第i个物品放入背包
          if (states[j]==true) states[j+items[i]] = true;
        }
      }
      for (int i = w; i >= 0; --i) { // 输出结果
        if (states[i] == true) return i;
      }
      return 0;
    }
    

    0-1 背包问题升级版

    回溯算法

    private int maxV = Integer.MIN_VALUE; // 结果放到maxV中
    private int[] items = {2,2,4,6,3};  // 物品的重量
    private int[] value = {3,4,8,9,6}; // 物品的价值
    private int n = 5; // 物品个数
    private int w = 9; // 背包承受的最大重量
    public void f(int i, int cw, int cv) { // 调用f(0, 0, 0)
      if (cw == w || i == n) { // cw==w表示装满了,i==n表示物品都考察完了
        if (cv > maxV) maxV = cv;
        return;
      }
      f(i+1, cw, cv); // 选择不装第i个物品
      if (cw + weight[i] <= w) {
        f(i+1,cw+weight[i], cv+value[i]); // 选择装第i个物品
      }
    }
    

    动态规划-二维数组

    public static int knapsack3(int[] weight, int[] value, int n, int w) {
      int[][] states = new int[n][w+1];
      for (int i = 0; i < n; ++i) { // 初始化states
        for (int j = 0; j < w+1; ++j) {
          states[i][j] = -1;
        }
      }
      states[0][0] = 0;
      if (weight[0] <= w) {
        states[0][weight[0]] = value[0];
      }
      for (int i = 1; i < n; ++i) { //动态规划,状态转移
        for (int j = 0; j <= w; ++j) { // 不选择第i个物品
          if (states[i-1][j] >= 0) states[i][j] = states[i-1][j];
        }
        for (int j = 0; j <= w-weight[i]; ++j) { // 选择第i个物品
          if (states[i-1][j] >= 0) {
            int v = states[i-1][j] + value[i];
            if (v > states[i][j+weight[i]]) {
              states[i][j+weight[i]] = v;
            }
          }
        }
      }
      // 找出最大值
      int maxvalue = -1;
      for (int j = 0; j <= w; ++j) {
        if (states[n-1][j] > maxvalue) maxvalue = states[n-1][j];
      }
      return maxvalue;
    }
    

    动态规划-一维数组

    public static int knapsack4(int[] weight, int[] value, int n, int w) {
            int[] states = new int[w + 1];
            for (int i = 0; i < w + 1; ++i) { // 初始化states
                states[i] = -1;
            }
            states[0] = 0;
            if (weight[0] <= w) {
                states[weight[0]] = value[0];
            }
            for (int i = 1; i < n; ++i) { //动态规划,状态转移
                for (int j = w - weight[i]; j >= 0; --j) {//把第i个物品放入背包
                    if (states[j] >= 0) {
                        int v = states[j] + value[i];
                        if (v > states[j + weight[i]]) {
                            states[j + weight[i]] = v;
                        }
                    }
                }
            }
            // 找出最大值
            int maxvalue = -1;
            for (int i = w; i >= 0; --i) { // 输出结果
                if (states[i] > maxvalue) {
                    maxvalue = states[i];
                }
            }
            return maxvalue;
        }
    

    相关文章

      网友评论

        本文标题:初识动态规划

        本文链接:https://www.haomeiwen.com/subject/lihfkktx.html