LeetCode | 174. Dungeon Game (Hard)

来源:互联网 发布:python instance类型 编辑:程序博客网 时间:2024/06/07 05:08


题目:

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.


题意:

输入一个m*n大小的矩阵,矩阵包含正数和负数,目标是骑士K从左上角出发,到达右下角,要求设置K的一个初始能量值,保证K所处任何位置加上dungeon的值都大于0。求初始值最小是多少?

思路:

因为前面几题是在寻找矩阵的路径,刚开始惯性思维从左上角到达右下角开始思考。

dp[i][j] 需要记录当前(i, j)仍剩余的能量值(正负都行);cost[i][j]记录当前(i, j)的最小值(负数)以得到最终的初始值。

代码如下:

int calculateMinimumHP1(vector<vector<int>>& dungeon) {        int m = dungeon.size();int n = m > 0 ? dungeon[0].size() : 0;if(!m && !n)return 0;vector<vector<int>> cost(m+1, vector<int>(n+1));vector<vector<int>> dp(m+1, vector<int>(n+1));dp[0][0] = dungeon[0][0];cost[0][0] = dungeon[0][0];for(int i = 1; i<m; i++){dp[i][0] = dp[i-1][0] + dungeon[i][0];cost[i][0] = min(cost[i-1][0], dp[i-1][0]+dungeon[i][0]);}for(int i = 1; i<n; i++){dp[0][i] = dp[0][i-1] + dungeon[0][i];cost[0][i] = min(cost[0][i-1], dp[0][i-1]+dungeon[0][i]);}for(int i = 1; i<m; i++){for(int j = 1; j<n; j++){if(cost[i-1][j] == cost[i][j-1]){if(dp[i-1][j] > dp[i][j-1])dp[i][j] = dp[i-1][j] + dungeon[i][j];elsedp[i][j] = dp[i][j-1] + dungeon[i][j];cost[i][j] = min(cost[i-1][j], dp[i][j]);}else if(cost[i-1][j] > cost[i][j-1]){dp[i][j] = dp[i-1][j] + dungeon[i][j];cost[i][j] = min(cost[i-1][j], dp[i][j]);}else{dp[i][j] = dp[i][j-1] + dungeon[i][j];cost[i][j] = min(cost[i][j-1], dp[i][j]);}}}for(int i = 0; i<m; i++){for(int j = 0; j<n; j++)cout << dp[i][j] << ' ';cout << endl;}for(int i = 0; i<m; i++){for(int j = 0; j<n; j++)cout << cost[i][j] << ' ';cout << endl;}return cost[m-1][n-1] >= 0 ? 1 : -cost[m-1][n-1] + 1;    }

好,结果是。。。一直WA。。。refine了一些感觉还是思路不通。看了题解,才发现自己把问题想复杂了。换个角度看问题,其实我们需要解决的问题是希望从(m-1, n-1)到(0, 0)的过程中,记录当前节点需要的能量值,后续步骤的能量值不能影响前面步数的能量,所以当能量值过剩统一设为1。

AC代码如下:

int calculateMinimumHP(vector<vector<int>>& dungeon) {        int m = dungeon.size();int n = m > 0 ? dungeon[0].size() : 0;if(!m && !n)return 0;vector<vector<int>> dp(m+1, vector<int>(n+1));dp[m][n-1] = 1;dp[m-1][n] = 1;for(int i = m-1; i>=0; i--)dp[i][n-1] = dp[i+1][n-1] - dungeon[i][n-1] <= 0 ? 1 : dp[i+1][n-1] - dungeon[i][n-1];for(int i = n-2; i>=0; i--)dp[m-1][i] = dp[m-1][i+1] - dungeon[m-1][i] <= 0 ? 1 : dp[m-1][i+1] - dungeon[m-1][i];for(int i = m-2; i>=0; i--){for(int j = n-2; j>=0; j--){int tmp = min(dp[i][j+1], dp[i+1][j]) - dungeon[i][j];dp[i][j] = tmp <= 0 ? 1 : tmp;}}return dp[0][0];    }


一道题目写了4个小时= =# 要多加练习才行!

PS:近期多线程负载要求高,加油!坚持就是胜利!