题目:
给定一个二维数组map。含义是一张地图,例如,如下矩阵:
-2 -3 3
-5 -10 1
0 30 -5
游戏的规则如下:
骑士从左上角出发,每次只能向右或向下走,最后到达右下角见到公主。
地图中每个位置的值代表骑士要遭遇的事情,如果是负数,说明此处有怪兽,要让骑士损失血量。如果是非负数,代表此处有血瓶,能让骑士回血。
骑士从左上角到右下角的过程中,走到任何一个位置时,血量都不能少于1。
为了保证骑士能见到公主,初始血量至少是多少?根据map,返回初始血量。
定义和地图代傲一样的矩阵,记为dp,dp[i][j]的含义是如果骑士要走上位置(i,j),并且从该位置选一条最优的路径,最后走到右下角,骑士起码应该具备的血量。根据dp的定义,我们最终需要的是dp[0][0]的结果。
dp[i][j]有两个选择向右或者是向下。
public int minHP1(int[][] m){
if(m == null || m.length == 0 || m[0] == null || m[0].length == 0){
return 1;
}
//因为整体要算dp[0][0]的值,所以计算初始化最后一行所有的列的值,循环的时候从
//最后一行开始就行
int row = m.lenght;
int col = m[0].length;
int[][] dp = new int[row--][col--];
//下面的row和col已经做了减减处理
dp[row][col] = m[row][col] > 0 ? 1 : -m[row][col] + 1;
for(int j = col -1; j>=0;j--){
dp[row][j] = Math.max(dp[row][j+1] - m[row][j],1);
}
int right = 0;
int down = 0;
for(int i = row -1;i>=0;i--){
dp[i][col] = Math.max(dp[i+1][col] - m[i][col],1);
for(int j=col-1;j>=0;j--){
right = Math.max(dp[i][j+1] - m[i][j],1);
down = Math.max(dp[i+1][j] - m[i][j],1);
dp[i][j] = Math.min(right,down);
}
}
return dp[0][0];
}
public static int minHP2(int[][] m){
if(m==null || m.length ==0 || m[0] == null || m[0].length == 0){
return 1;
}
int more Math.max(m.length,m[0].length);
int less Math.min(m.length,m[0].length);
boolean rowmore = more == m.length;
int[] dp[] = new int[less];
int tmp = m[m.length-1][m[0].length -1];
dp[less-1] = tmp > 0?1:-tmp +1;
int row = 0;
int col = 0;
for(int j = less -2;j>=0;j--){
row = rowmore ? more -1:j;
col = rowmore ? j : more -1;
dp[j] = Math.max(dp[j+1] - m[row][col],1);
}
int choosen1 = 0;
int choosen2 = 0;
for(int i = more -2;i>=0;i--){
row = rowmore ? i : less -1;
col = rowmore ? less -1:i;
dp[less - 1 ] = Math.max(dp[less - 1] - m[row][col],1);
for(int j = less -2;j>=0;j--){
row = rowmore ? i:j;
col = rowmore ? j:i;
choosen1 = Math.max(dp[j] - m[row][col],1);
choosen2 = Math.max(dp[j +1] - m[row][col],1);
dp[j] = Math.min(choosen1,choosen2);
}
}
return dp[0];
}