题目描述:有一个m×n的矩阵,现要从左下角走到右上角,并且方向只能是向上或者向右,
现规定一条路径的权值为走此路径所经过的值的和。给定一个矩阵,请找出权值最大的一条
路径。
Example:
2 5 6
3 9 4
7 9 1
所找到的路径为7->9->9->5->6,权值为36。
首先我们来介绍一下动态规划的思想:
动态规划程序设计中,我们主要利用了问题的两个性质:最优子结构和子问题重叠。最优子结构指问题的最优解包含了子问题的最优解,它是动态规划方法可
行的理论基础。而一个问题具有子问题重叠性质是指用递归算法自顶向下解这个问题时,并不总是产生新的子问题,有些子问题被重复求解多次。
因为最优子结构性质,动态规划求问题最优解时,可以转化为求子问题的最优解,而对解决过的问题,动态规划则记录它的结果,当再次遇上已解决的问题,就可以直接利用结果。子问题重叠性质保证了这样做是有意义的。但一般的搜索技术,对于某个子问题不管是否已经解决过,只要遇上,就会再次对这个子问题进行求解。很明显,动态规划与一般搜索技术最大不同的地方就是记录了已求解过的问题的结果。这里包含了两个方面的内容 :子问题的记录和子问题结果的记录。其中,子问题的记录是最重要,也是最为复杂的,它就是通常我们所说的状态表示。通常我们用一个数、一组数或一个向量来实现状态表示。但无论采取什么方法,从动态规划的原理来看,状态表示要满足两个要求:正确、合理描述子问题和描述的子问题满足最优子结构性质;从算法实现角度来看,状态表示必须能够用基本数据结构实现并且能满足空间要求。
现在我们来看上面的这个问题:(path[][]是矩阵的描述)
状态表示: 用maxpath[i][j]表示走到第i行第j列的最大权值,那么maxpath[i][j]的最优解
包含子问题maxpath[i-1][j]和maxpath[i][j+1]的最优解,然后我们采取倒推法,则可得到我
们的状态转移方程:
maxpath[i][j] = MAX{ maxpath[i-1][j], maxpath[i][j+1] } + maxpath[i][j];
maxpath[0][n-1] = path[0][n-1];
这样,最大的路径权值可以通过比较底层的分数求得。一般情况下,我们找到的状态表示应能刻划子问题的特征,困难的是如何找到描述的子问题能满足最优子结构性质的状态表示,而这一点恰恰是决定该问题能否应用动态规划方法的重要因素。状态表示1-1描述的问题是正确的,但它不能满足最优子结构性质,使得无法用它来建立动态规划数学模型。状态分析的过程实际上是分析问题最优子结构的过程,不同的状态表示正是从不同的角度去试图刻划问题的最优子结构。只有状态表示描述的子问题能满足最优子结构性质,我们才能在此基础上正确的建立起动态规划数学模型。
package com.he;
public class test31 {
private void print(int path[][])// 打印路径
{
for (int i = 0; i < path.length; i++) {
for (int j = 0; j < path[i].length; j++) {
System.out.print(path[i][j] + " ");
}
System.out.println("");
}
}
public int findMaxPath(int path[][]) {
for (int i = path[0].length - 2; i >= 0; i--)// 第一行的值
{
path[0][i] += path[0][i + 1];
}
for (int i = 1; i < path.length; i++) // 最后一列的值
{
path[i][path[i].length - 1] += path[i - 1][path[i - 1].length - 1];
}
for (int i = 1; i < path.length; i++)// 倒推法,利用上面的公式
{
for (int j = path[i].length - 2; j >= 0; j--) {
if (path[i - 1][j] >= path[i][j + 1]) {
path[i][j] = path[i][j] + path[i - 1][j];
} else {
path[i][j] = path[i][j] + path[i][j + 1];
}
}
}
print(path);
return path[path.length - 1][0];// 最后位置的值即为要求的最大权值
}
public static void main(String args[]) {
int[][] path = { { 2, 5, 6 }, { 3, 9, 4 }, { 7, 9, 1 } };
System.out.println(new test31().findMaxPath(path));
}
}
—————————————————————————————————————————————————————————————————
题目描述
有一个矩阵map,它每个格子有一个权值。从左上角的格子开始每次只能向右或者向下走,最后到达右下角的位置,路径上所有的数字累加起来就是路径和,返回所有的路径中最小的路径和。
给定一个矩阵map及它的行数n和列数m,请返回最小路径和。
动态规划求解过程.
假定给定一个N*M的矩阵 假定N等于4 M等于4
1 2 3 4
4 8 3 2
6 1 4 5
7 3 7 8
现在生成一个大小为N*M的矩阵dp,dp[i][j]的含义为从(0,0)点到(i,j)点的最小路径
显然 第一行的路径值就为从0,0点到i,j每一点值的和
1 3 4 10
1
5
11
18
置dp[0][0] = 矩阵值[0][0]; 对于第一行来说dp[i][0] = dp[i–1][0]+矩阵值[i][0];对于第一列来说 dp[0][i] = dp[0][i–1]+矩阵值[0][i];
对于除第一行第一列之后其他的位置有dp[i][j] = min(dp[i-1][j],dp[i][j-1])+矩阵值[i][j];
至此,状态转移方程求解完毕