【原创】leetCodeOj --- Dungeon Game 解题报告

本文探讨了一个利用动态规划求解迷宫寻宝问题的方法,通过定义状态转移方程,逐步推导出从起点到终点所需最小初始生命值。文章详细解释了状态转移的逻辑,并提供了代码实现,帮助读者理解如何应用动态规划解决类似路径优化问题。
摘要由CSDN通过智能技术生成

原题地址:

https://oj.leetcode.com/problems/dungeon-game/

 

题目内容:

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-101
1030-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.

 

方法:

唉,leetcode也越来越水了。这题是比较单纯的DP题,标Medium还行,标Hard有点让人失望。

 

步入正题。

定义状态dp[i][j]为,进入i,j坐标【前】,至少需要多少HP,才能从i,j坐标到达终点。

由于在一个坐标时,不是走右就是走下,所以:

设next = min(dp[i + 1][j] , dp[i][j + 1]) , pos = dungeon[i][j]

dp[i][j] = pos >= next ? 1 : next - pos

 

简单讲一下。首先next的值,是在i,j坐标上的right、down两个选择中,能够以最少HP到达终点的坐标的所需的最少HP值。(有点拗口。。比如说往右走需要进入右边以前有10点HP才能最终到达终点,而往下走则需要5点,那么next的值就是5)

其次,如果i,j坐标能够提供足够的HP保证走到next,那么进入i,j坐标前有1点HP就足够了,保证不死就行;反之,需要用next - pos来算出进入i,j坐标前需要的HP点数。

 

具体实现上,用一个一维dp数组就可以模拟整个过程了,不需要真的申请一个二维数组。具体可以参考代码,如果不能理解可以留言,我再详细讲讲。

 

具体代码:

class Solution {
public:
    int calculateMinimumHP(vector<vector<int> > &dungeon) {
        int ylength = dungeon.size(); // how many sub-array
        if (ylength == 0)
            return 0;
        int xlength = dungeon[0].size(); // how many elements that sub-array contains
        if (xlength == 0)
            return 0;
        int max = ~(1 << 31);
        vector<int> res;
        for (int i = 0; i < xlength; i ++) {
            res.push_back(0);
        }
        for (int i = ylength - 1; i >= 0; i --) {
            for (int j = xlength - 1; j >= 0; j --) {
                int x = j + 1;
                int y = i + 1;
                int right = x < xlength ? res[x] : max;
                int down  = y < ylength ? res[j] : max;
                if (right == max && down == max) {
                    res[j] = dungeon[ylength - 1][xlength - 1] >= 0 ? 1 : 1 - dungeon[ylength - 1][xlength - 1]; // final point
                } else {
                    int tmp = right > down ? down : right;
                    int pos = dungeon[i][j];
                    if (pos >= tmp) {
                        res[j] = 1;   
                    } else {
                        res[j] = tmp - pos;
                    }
                }
            }
        }
        return res[0];
    }

};

  

转载于:https://www.cnblogs.com/shadowmydx/p/4231717.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值