LeetCode.174

来源:互联网 发布:淘宝同行跳失率怎么看 编辑:程序博客网 时间:2024/06/11 07:39

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.


起初使用的是分步递归的方式,并记录每条路线的最低需求Hp。但是只能通过40个测试用例,最终还是超时无法全部通过。在这里记录下代码,以后有空尝试优化。

static vector<int> MinimumHP;void digui(vector< vector<int> > dungeon, int min_hp, int now_hp){now_hp += dungeon[0][0];min_hp = min_hp < now_hp ? min_hp : now_hp;vector< vector<int> > vec;int h = dungeon.size(), w = dungeon[0].size();if(h > 1){vec.clear();vec.resize(h - 1);for(int i = 0; i < h - 1; i++){vec[i].resize(w);}for(int i = 0; i < vec.size(); i++){for(int j = 0; j < vec[0].size(); j++){vec[i][j] = dungeon[i + 1][j]; }}digui(vec, min_hp, now_hp);}if(w > 1){vec.clear();vec.resize(h);for(int i = 0; i < h; i++){vec[i].resize(w - 1);}for(int i = 0; i < vec.size(); i++){for(int j = 0; j < vec[0].size(); j++){vec[i][j] = dungeon[i][j + 1]; }}digui(vec, min_hp, now_hp);}if(w == 1 && h == 1){MinimumHP.push_back(min_hp);}}int calculateMinimumHP(vector< vector<int> >& dungeon){if(dungeon.empty()){return 1;}vector< vector<int> > v = dungeon;digui(v, 0, 0);int hp = 1 - *max_element(MinimumHP.begin(), MinimumHP.end());MinimumHP.clear();return hp;}

而后在讨论模块中的提示下使用了动态规划的方式,通过对矩阵分块来倒推求得结果。


思路:1.以右下角1个数据为起始块;

  2.分别以向左和向上(两条边)的方向逐步求得进入对应块所需的最低Hp,并记录在对应位置;

3.剩余的部分则从右下方开始,取进入下方块和进入右方块中需求Hp较低的再减去进入当前点的血量变化,即求得进入该组合块所需的最低Hp;


文字可能难以理解,下方将贴上代码:

int calculateMinimumHP(vector< vector<int> >& dungeon){if(dungeon.empty()){return 1;}int h = dungeon.size(), w = dungeon[0].size(), temp = 0;int arr[h][w];arr[h - 1][w - 1] = 1 > 1 - dungeon[h - 1][w - 1] ? 1 : 1 - dungeon[h - 1][w - 1];for(int i = w - 2; i >= 0; i--){arr[h - 1][i] = 1 > (arr[h - 1][i + 1] - dungeon[h - 1][i]) ? 1 : (arr[h - 1][i + 1] - dungeon[h - 1][i]);}for(int i = h - 2; i >= 0; i--){arr[i][w - 1] = 1 > (arr[i + 1][w - 1] - dungeon[i][w - 1]) ? 1 : (arr[i + 1][w - 1] - dungeon[i][w - 1]);}for(int i = h - 2; i >= 0; i--){for(int j = w - 2; j >= 0; j--){temp = arr[i + 1][j] < arr[i][j + 1] ? arr[i + 1][j] : arr[i][j + 1];arr[i][j] = 1 > (temp - dungeon[i][j]) ? 1 : (temp - dungeon[i][j]);}}return 1 > arr[0][0] ? 1 : arr[0][0];}



原创粉丝点击