动规解题的一般思路
1)将原问题分解为子问题
2)确定状态
3)确定一些初始状态(边界状态)的值
4)确定状态转移方程
能用动规解决的问题的特点
1)问题具有最优子结构性质
2)无后效性
动归的常用两种形式
1)递归型
优点:直观,容易编写
缺点:可能会因为递归层数太深导致爆栈,函数调用带来额外时间开销。无法使用滚动数组节省空间。总体来说,比递归型慢。
2)递推型
效率高,有可能使用滚动数组节省空间。
题目29 数字三角形
7
3 8
8 1 0
2 7 4 4
4 5 2 6 5
在上面的数字三角形中寻找一条从顶部到底边的路径,使得 路径上所经过的数字之和最大。路径上的每一步都只能往左下或 右下走。只需要求出这个最大和即可,不必给出具体路径。 三角形的行数大于1小于等于100,数字为 0 - 99
输入格式:
5 //三角形行数。
下面是三角形
7
3 8
8 1 0
2 7 4 4
4 5 2 6 5
要求输出最大
数组三角形的递归程序:时间复杂度O(2^n)
public class _29数字三角形 {
static int MAX = 101;
static int n;
static int[][] D = new int[MAX][MAX];
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
n = sc.nextInt();
for (int i=1; i<=n; ++i) {
for (int j=1; j<=i; ++j) {
D[i][j] = sc.nextInt();
}
}
System.out.println(MaxSum(1, 1));
}
static int MaxSum(int i, int j) {
if (i==n) {
return D[i][j];
}
int x = MaxSum(i+1, j);
int y = MaxSum(i+1, j+1);
return Math.max(x, y) + D[i][j];
}
}
数字三角形的记忆递归型动规程序
public class _29数字三角形2 {
static int MAX = 101;
static int[][] D = new int[MAX][MAX];
static int[][] maxSum = new int[MAX][MAX];
static int n;
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
n = sc.nextInt();
for (int i=1; i<=n; ++i) {
for (int j=1; j<=i; ++j) {
D[i][j] = sc.nextInt();
maxSum[i][j] = -1;
}
}
System.out.println(MaxSum(1, 1));
}
static int MaxSum(int i, int j) {
if (maxSum[i][j] != -1) {
return maxSum[i][j];
}
if (i==n) {
maxSum[i][j] = D[i][j];
} else {
int x = MaxSum(i+1, j);
int y = MaxSum(i+1, j+1);
maxSum[i][j] = Math.max(x, y) + D[i][j];
}
return maxSum[i][j];
}
}
数字三角形的记忆递推型动规程序
public class _29数字三角形3 {
static int MAX = 101;
static int[][] D = new int[MAX][MAX];
static int[][] maxSum = new int[MAX][MAX];
static int n;
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
n = sc.nextInt();
for (int i=1; i<=n; ++i) {
for (int j=1; j<=i; ++j) {
D[i][j] = sc.nextInt();
}
}
for (int i=1; i<=n; ++i) {
maxSum[n][i] = D[n][i];
}
for (int i=n-1; i>=1; --i) {
for (int j=1; j<=i; ++j) {
maxSum[i][j] = Math.max(maxSum[i+1][j],maxSum[i+1][j+1]) + D[i][j];
}
}
System.out.println(maxSum[1][1]);
}
}
空间优化版本
public class _29数字三角形4 {
static int MAX = 101;
static int[][] D = new int[MAX][MAX];
static int n;
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
n = sc.nextInt();
for (int i=1; i<=n; ++i) {
for (int j=1; j<=i; ++j) {
D[i][j] = sc.nextInt();
}
}
for (int i=n-1; i>=1; --i) {
for (int j=1; j<=i; ++j) {
D[n][j] = Math.max(D[n][j], D[n][j+1] + D[i][j]); // 使用滚动数组
}
}
System.out.println(D[n][1]);
}
}