数字三角形问题
给定一个由 n 行数字组成的数字三角形,试设计一个算法,计算出 从三角形的顶至底的一条路径,使该路径经过的数字总和最大。
试写出递归算法,再利用实验中的思路把它转化为备忘录法和动态规划算法
1:递归算法
public class DynamicProgramming {
// 三角形行数
private int n = 5;
// 三角形数据
private int[][] nums = {
{ 9},
{12, 15},
{10, 6, 8},
{ 2, 18, 9, 5},
{19, 7, 10, 4, 16},
};
// 递归算法
public int test(int x,int y) {
//如果已经到三角形底部就直接返回底部的数据
if(x == n-1) {
return nums[x][y];
}
//每个位置下面有两个选择,选择最大和的那个
return (nums[x][y] + (test(x+1,y) >= test(x+1,y+1) ? test(x+1,y) : test(x+1,y+1)));
}
public static void main(String[] args) {
DynamicProgramming dynamicProgramming = new DynamicProgramming();
System.out.println(dynamicProgramming.test(0,0));
}
}
2:带备忘录的递归算法
public class DynamicProgramming {
// 三角形行数
private int n = 5;
// 三角形数据
private int[][] nums = {
{ 9},
{12, 15},
{10, 6, 8},
{ 2, 18, 9, 5},
{19, 7, 10, 4, 16},
};
// 备忘录
int[][] table = new int[n][n];
/*
* 描述:用于计算三角形数据的最大和
* 参数:三角形数据二维数组的坐标x和y
* 返回值:三角形数据的最大和
* */
public int test(int x,int y) {
//如果已经到三角形底部就直接返回底部的数据
if(x == n-1) {
return nums[x][y];
}
//如果备忘录里面有值,直接返回备忘录数组中的值
if(table[x][y] != 0) {
return table[x][y];
}
//每个位置下面有两个选择,选择最大和的那个,当前位置的三角形数据与最大和的那个相加
return table[x][y] = (nums[x][y] + (test(x+1,y) >= test(x+1,y+1) ? test(x+1,y) : test(x+1,y+1)));
}
public static void main(String[] args) {
DynamicProgramming dynamicProgramming = new DynamicProgramming();
System.out.println(dynamicProgramming.test(0,0));
}
}
3:动态规划法
public class DynamicProgramming {
// 三角形行数
private int n = 5;
// 三角形数据
private int[][] nums = {
{ 9},
{12, 15},
{10, 6, 8},
{ 2, 18, 9, 5},
{19, 7, 10, 4, 16},
};
// // 备忘录
// int[][] table = new int[n][n];
//
// /*
// * 描述:用于计算三角形数据的最大和
// * 参数:三角形数据二维数组的坐标x和y
// * 返回值:三角形数据的最大和
// * */
// public int test(int x,int y) {
// //如果已经到三角形底部就直接返回底部的数据
// if(x == n-1) {
// return nums[x][y];
// }
// //如果备忘录里面有值,直接返回备忘录数组中的值
// if(table[x][y] != 0) {
// return table[x][y];
// }
// //每个位置下面有两个选择,选择最大和的那个,当前位置的三角形数据与最大和的那个相加
// return table[x][y] = (nums[x][y] + (test(x+1,y) >= test(x+1,y+1) ? test(x+1,y) : test(x+1,y+1)));
// }
/*
* 描述:用于计算三角形数据的最大和
* 参数:三角形数据二维数组的坐标x和y
* 返回值:三角形数据的最大和
* */
public int test1() {
// 对nums二维数组的行作遍历,从倒数第二行开始
int start = n-2;
for(int i = start; i >= 0; i--) {
// 每一行的长度
int j = nums[i].length;
// 对nums二维数组的行中的数组元素作遍历
for(int k = 0; k < j; k++) {
nums[i][k] += (nums[i+1][k] >= nums[i+1][k+1] ? nums[i+1][k] : nums[i+1][k+1]);
}
}
// 返回三角形顶的数据,此时的三角形顶的值就是三角形最大和
return nums[0][0];
}
public static void main(String[] args) {
DynamicProgramming dynamicProgramming = new DynamicProgramming();
// System.out.println(dynamicProgramming.test(0,0));
System.out.println(dynamicProgramming.test1());
}
}
在这个实验中,我了解到了动态规划的基本思想,即聪明的枚举,尽量让以前走过的步骤不白走,在以后的步骤中能用上以前计算过的数据,做到不重复计算,实验分为三步,第一步就是平常的递归算法,第二步就是不做重复计算的递归算法,第三步是节省了空间的非递归算法(自底向上寻求答案)