题目描述
一个恶魔抓住了公主,并且把她囚禁在地牢的右下角。这个地牢是个M*N的矩阵。 骑士被囚禁在地牢的左上角,骑士必须穿过重重关卡拯救公主。
骑士有初始生命值由一个正数表示。如果他的生命值降为0及其以下,则骑士死亡。在地牢里的一些房间有恶魔看守,当骑士进入这些房间时,会损失相应生命值(即矩阵中对应的负数);而另外一些房间则存在一些物品,能给骑士加相应的血量(即矩阵中的正数)。
为了能尽快到达公主在的房间,骑士只向右,向下移动。每次只能移动一步。
写一个函数求骑士能拯救公主的最低初始血量。
原题以及例子如下,
在做这道题之前,如果没有任何思路,可以先做做与这道题很类似的几道题——62和64题。
这种题很明显是要使用动态规划的。使用动态规划后能省去很多重复的步骤。在完成这道题时,要先确定目标。比如,这里我们要寻找的是最低初始生命值,如果从起点开始向终点出发,那么是很难得到这个值的,比如你只是简单的求到终点的最小代价,你得到的并不是可靠的最低初始生命值,因为路途中会经历走的道路是否需要更高的初始生命值是不明确的,不信的话,可以试试上面那个例子。
这道题求的是最低初始生命值,那么我们规划的应该是到某个格子需要的最低生命值。那么我们就只能以那个格子为起始点,以原来的起点为终点来解决这个问题。只要想到这儿,那么这个问题就很好解决了。可能我表述的不是很清楚,结合代码来看一下吧。
代码如下,
class Solution {
public:
int calculateMinimumHP(vector<vector<int>>& dungeon) {
int m = dungeon.size();
int n = dungeon[0].size();
vector<vector<int> > cost(m + 1, vector<int>(n + 1, INT_MAX));
cost[m][n-1] = 1;
cost[m-1][n] = 1;
for (int i = m - 1; i >= 0; --i) {
for (int j = n - 1; j >= 0; --j) {
cost[i][j] = min(cost[i][j+1], cost[i+1][j]) - dungeon[i][j];
cost[i][j] = cost[i][j] <= 0 ? 1 : cost[i][j];
}
}
return cost[0][0];
}
};