LeetCode 解题报告 Dungeon Game

来源:互联网 发布:linq for java 编辑:程序博客网 时间:2024/05/16 00:49

The demons had captured the princess (P) and imprisoned her in the bottom-right corner of a dungeon. The dungeon consists of M x N rooms laid out in a 2D grid. Our valiant knight (K) was initially positioned in the top-left room and must fight his way through the dungeon to rescue the princess.

The knight has an initial health point represented by a positive integer. If at any point his health point drops to 0 or below, he dies immediately.

Some of the rooms are guarded by demons, so the knight loses health (negative integers) upon entering these rooms; other rooms are either empty (0's) or contain magic orbs that increase the knight's health (positive integers).

In order to reach the princess as quickly as possible, the knight decides to move only rightward or downward in each step.


Write a function to determine the knight's minimum initial health so that he is able to rescue the princess.

For example, given the dungeon below, the initial health of the knight must be at least 7 if he follows the optimal path RIGHT-> RIGHT -> DOWN -> DOWN.

-2 (K)-33-5-1011030-5 (P)

Notes:

  • The knight's health has no upper bound.
  • Any room can contain threats or power-ups, even the first room the knight enters and the bottom-right room where the princess is imprisoned.

Credits:
Special thanks to @stellari for adding this problem and creating all test cases.

题意:

就是从左上角走到右下角,只能往下往右走,格子里的数字代表能量,如果是正数就往骑士身上增加相应的能量,如果是负数就会扣除骑士身上相应的能量,如果骑士身上的能量<=0那么骑士就死了,题目问初始时骑士身上最少要多少能量才能让骑士从左上角顺利到达右下角。

解题思路:

1.本题可以用搜索来做

从起始点到终止点搜索所有可能找出最小的,很明显这种方法会非常耗时,地图不是很大的情况下就会运行的很慢了。所以应该换个思路

2.用动态规划

用一个二维数组来存储到达每个点所消耗的能量值,从终点开始遍历回起始点,最后起始点的值就是最终的答案。

举个栗子:

-2 (K)-33-5-1011030-5 (P)拿题目中的图来说吧,我们先看终点,-5也就是说骑士到达终点前的节点时身上最少要保证6个能量,那么终点之前的那个节点需要多少呢?

        6

因为只有两个点能到达终点,一个是终点上面的点,一个是下面的点,方便起见,我们分别称为up和left,那么我们先看up吧,因为要保证终点是6,所以up点的值为6-1=5就可以满足了。再看left,只要我们能满足6-30=-14就可以了,可以吗?当然不可以,因为我们不能让骑士的能力为负值,所以最小值1,

     5 16我们在看up的up点,5-3=2>0满足条件,再看left的left,1-10=-9<1所以是1

  2 *5116接下来我们再看*处的方格内应该怎么写?

我们想,如果*往下走需要消耗1个能量,如果往右走需要消耗5个能量,那应该往哪走才能保证最低消耗呢?如果还不知道就去问你的小学数学老师吧!所以我们选在*的down方格的基础上计算,因为*本身要消耗10个能量,所以1--10=11

  2 115116同理也就能算出来:

 526115116最后得到:

7526115116
刚刚模拟整个实现过程,其实也就是程序的实现过程,能看出,这种方法需要建立一个二维数组来存储,空间复杂度为:O(m*n)并且最后需要遍历这个表格,所以时间复杂度为:O(m*n)也就是O(n*n)。

下面是我的代码实现

public class Solution {   public int calculateMinimumHP(int[][] dungeon) {if(dungeon.length == 0)return 0;int m = dungeon.length;int n = dungeon[0].length;int dp[][] = new int [m][n];//首先确定最后一个方格需要花费多少dp[m-1][n-1] = dungeon[m-1][n-1] >= 0 ? 1 : -dungeon[m-1][n-1] + 1;//分别按行和列根据当前已知方格来确定前一个方格需要花费多少for(int i = m - 2; i >= 0; i--) {dp[i][n-1] = Math.max(dp[i+1][n-1] - dungeon[i][n-1], 1);}for(int i = n - 2; i >= 0; i--) {dp[m-1][i] = Math.max(dp[m-1][i+1] - dungeon[m-1][i], 1);}for(int i = m - 2; i >= 0; i-- ) for(int j = n - 2; j >= 0; j--) {dp[i][j] = Math.max(1, Math.min(dp[i][j+1], dp[i+1][j]) - dungeon[i][j]);}return dp[0][0];}}
还能再优化吗?

当然可以了,空间复杂度这里为O(n*n),是不是可以使用O(n)就能解决问题呢?



0 0