动态规划(Dynamic Programming)—— Java解释

一、基本思想

动态规划(Dynamic Programming)算法的核心思想是:将大问题划分为小问题进行解决,并将子问题的求解结果存储起来避免重复求解,从而一步步获取最优解的处理算法。

动态规划算法与分治算法类似,其基本思想也是将待求解问题分解成若干个子问题,先求解子问题,然后从这些子问题的解得到原问题的解。与分治法不同的是,适合于用动态规划求解的问题,经分解得到子问题往往不是互相独立的。 ( 即下一个子阶段的求解是建立在上一个子阶段的解的基础上,进行进一步的求解 )

动态规划的特性主要包括:

  1. 分解原问题:动态规划将原问题分解为若干个相似的子问题,这些子问题之间相互独立,并且每个子问题只需要解决一次。
  2. 储存子问题的解:动态规划会储存子问题的解,以避免重复计算,这是动态规划能够高效解决复杂问题的关键。
  3. 状态转移方程:动态规划的本质在于对问题状态的定义和状态转移方程的定义(状态以及状态之间的递推关系)。
  4. 无后效性:每个状态都是“过去历史的一个完整总结”,也就是说,每个状态都包含了它过去的历史信息,而不会受到未来状态的影响。
  5. 阶段性和相互联系性:动态规划通常将问题划分为若干个阶段,每个阶段都对应着一组状态,这些状态之间相互联系,构成了整个问题的状态转移过程。
  6. 决策变量和允许决策集合:在动态规划中,每个阶段都包含若干个决策变量,这些决策变量的取值范围称为允许决策集合。
  7. 状态变量和状态集合:描述各阶段状态的变量称为状态变量,常用sk表示第k阶段的状态变量,状态变量sk的取值集合称为状态集合,用Sk表示。

二、案例说明——背包问题

动态规划可以通过填表的方式来逐步推进,得到最优解。在填表法中,会为每个子问题预先计算出最优解并填入表中,然后通过查表来获取原问题的最优解。

背包问题:有一个背包,容量为4磅 , 现有如下物品

物品 重量 价格
吉他(G) 1 1500
音响(S) 4 3000
电脑(L) 3 2000
  1. 要求达到的目标为装入的背包的总价值最大,并且重量不超出
  2. 要求装入的物品不能重复

背包问题主要是指一个给定容量的背包、若干具有一定价值和重量的物品,如何选择物品放入背包使物品的价值最大。其中又分01背包和完全背包(完全背包指的是:每种物品都有无限件可用)

这里的问题属于01背包,即每个物品最多放一个。而无限背包可以转化为01背包。

思路: 利用动态规划来解决。

假设背包容量为weight,有 n 个物品,每个物品的重量为 w[i],价值为 v[i]

  1. dp[i][j] 表示前 `i` 个 物品,容量为j时的最大价值。 —— 定义动态规划的状态,通常是数组或集合
  2. dp[i][j] = max(dp[i-1][j], dp[i-1][j-w[i]] + v[i]),表示在第i个物品和不放第i个物品中选取一个最优解。 —— 定义状态转移方程,根据问题最优解的定义,确定状态之间的转移关系
  3. dp[0][j] = 0,表示不选择任何物品时的价值为0。—— 确定最基本的子问题的解作为边界条件
  4. 填表,从第一个物品开始填表直到最后一个物品。—— 每个子问题的最优解填入对应的状态位置
  5. 查询最优解,dp[n][weight] 即前n个物品,容量为w时的最大价值。 —— 根据需求解的问题的目标状态去查询对应子问题的最优解
public staic int knapsack(int[] w, int[] v, int weight) {
	int n = w.length;
	int[][] dp = new int[n + 1][weigth + 1];
	for (int i = 0; i <= n; i++) {
		for (int j = 0; j <= weigth; j++) {
			if (i == 0 || j == 0) {
				dp[i][j] = 0;
			} else if (j < w[i - 1]) {
				dp[i][j] = dp[i - 1][j];
			} else {
				dp[i][j] = Math.max(dp[i - 1][j], dp[i - 1][j - w[i - 1]] + v[i - 1]);
			}
		}
	}
	return dp[n][weight];
}

动态规划(Dynamic Programming)—— Java解释_第1张图片

你可能感兴趣的:(算法,动态规划,java,算法)