动态规划a

本文深入探讨动态规划的概念,包括0-1背包问题、最优子结构、无后效性和重复子问题等核心特征。介绍了动态规划的解题思路,如五步曲法,并通过爬楼梯、最长递增子序列、不同路径等问题进行实例解析,帮助读者掌握动态规划的运用。
摘要由CSDN通过智能技术生成

动态规划

大部分动态规划能解决的问题,都可以通过回溯算法来解决,只不过回溯算法解决起来效率比较低,时间复杂度是指数级别的,动态规范在执行效率上要高很多,只管执行效率提高了,但是动态规划的空间复杂度也提高了,所以很多时候我们会说动态规划是一种空间换时间的算法思想。

基础知识点-问题模型

0-1背包问题

对于一组不同重量、不可分割的物品,我们需要选择一些装入背包,在满足背包最大重量限制的前提下,背包中物品总重量的最大值是多少呢?


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背包升级版

每个物品涉及到价值问题


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]; 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值