题目
- 在以m*n的棋盘的每一格都放有一个礼物,每一个礼物都有一定的价值;你可以从棋盘的左上角开始哪格子里的礼物,并每次向右或者向下移动一格,直到到达棋盘的右下角;给定一个棋盘及其上面的礼物,请计算你最左能拿到多少价值的礼物?
分析
- 典型动态规划的题,先定义第一个函数f(i,j)表示到达坐标为(i,j)的格子时能拿到的礼物总和的最大值;根据题目要求,我们有两种可能的途径到达坐标为(i,j)的格子:通过(i-1,j)或者(i,j-1);
- 所以f(i,j) = max(f(i-1,j),f(i,j-1))+gift【i,j】;
- gift【i,j】就是该位置的值
- 尽管用递归分析,但是有大量重复的计算,导致递归的代码并不是最优的;所以,用循环;
分析
- 核心方法maxValueOfGifts(传进来一个二维数组):
- 鲁邦性检查
- 得到该二维数组的行和列
- 再定义一个二维数组,用来存到达每一步的最大值
- 从左上角开始遍历二维数组:maxValue
- 定义两个变量用来存,该点的上两个数字哪个更大一点(因为只有两条路,能到达该点,所以比较这两个点的大小)
- 只有i》0,上面有数,才可能比较
- up = maxValue[i-1][j]
- 只有j》0,左边有数,才可能比较
- left = maxValue[i][j-1]
- 最后maxValue[i][j] = (up和left取大的)+该数a[i][j]
- 等全都遍历完,最后返回右下角的数
package No15_优化空间和时间效率;
//礼物的最大价值
public class MaxValueOfGifts {
public int maxValueOfGifts(int [][]a){
//鲁邦性检查
if(a == null || a.length <= 0 || a[0].length <= 0){
return -1;
}
//定义一个用来存到每个点的最大值
int maxValue[][] = new int[a.length][a[0].length];
for(int i = 0;i < a.length ;i++){
for(int j = 0;j < a[0].length;j++){
//有两种方式会达到该点,一个是左边,一个是上边
int left = 0;
int up = 0;
//当然,只有存在才能比较
if(i > 0){
up = maxValue[i-1][j];
}
if(j > 0){
left = maxValue[i][j-1];
}
maxValue[i][j] = Math.max(up, left) + a[i][j];
}
}
return maxValue[a.length-1][a[0].length-1];
}
// ====================测试代码====================
void test(String testName, int[][] values, int rows, int cols, int expected){
if(maxValueOfGifts(values) == expected)
System.out.println(testName+" solution1 passed");
else
System.out.println(testName+" solution1 FAILED");
}
void test1(){
// 三行三列
int values[][] = {
{ 1, 2, 3 },
{ 4, 5, 6 },
{ 7, 8, 9 }
};
int expected = 29;
test("test1",values, 3, 3, expected);
}
void test2(){
//四行四列
int values[][] = {
{ 1, 10, 3, 8 },
{ 12, 2, 9, 6 },
{ 5, 7, 4, 11 },
{ 3, 7, 16, 5 }
};
int expected = 53;
test("test2", values, 4, 4, expected);
}
void test3(){
// 一行四列
int values[][] = {
{ 1, 10, 3, 8 }
};
int expected = 22;
test("test3", values, 1, 4, expected);
}
void test4(){
int values[][] = {
{ 1 },
{ 12 },
{ 5 },
{ 3 }
};
int expected = 21;
test("test4", values, 4, 1, expected);
}
void test5(){
// 一行一列
int values[][] = {
{ 3 }
};
int expected = 3;
test("test5", values, 1, 1, expected);
}
void test6(){
// 空指针
int expected = 0;
test("test6", null, 0, 0, expected);
}
public static void main( String arg[]){
new MaxValueOfGifts().test1();
new MaxValueOfGifts().test2();
new MaxValueOfGifts().test3();
new MaxValueOfGifts().test4();
new MaxValueOfGifts().test5();
new MaxValueOfGifts().test6();
}
}