Leetcode 174 - Dungeon Game(二分+dp)

来源:互联网 发布:oracle数据库实训心得 编辑:程序博客网 时间:2024/05/22 05:17

题意

一个2D迷宫,公主在(m, n)的位置,骑士在(0, 0)的位置,并且有一个初始生命值。

现在骑士要去(m, n)的位置,只能向右或者向上走。每个格子的位置上,都有BUFF和DEBUFF,现在要保持骑士在任何时刻的生命值都要大于0,求骑士的初始状态的最小生命值。

思路

算法1

二分+dp。这是一个比较直观的思路,我们二分一下骑士初始的生命值,然后dp去判断是否合法。

状态表示d[i,j],在位置[i, j]上的生命值。

转移方程d[i,j]=max(d[i,j1],d[i1,j])+a[i,j]。且d[i,j1]d[i1,j]至少存在一个大于0。

目标状态d[m,n]>0

算法2

直接dp。我们从(m, n)的位置开始倒推(0, 0)位置的最小生命值。

转移方程d[i,j]=max(1,min(d[i+1,j],d[i,j+1])a[i,j])

代码

//algorithm 1const int maxn = 1005;#define INF 0x3e3e3e3eclass Solution {public:    int m, n;    vector<vector<int>> a;    int d[maxn][maxn];    int dfs(int i, int j, int x) {        if (d[i][j] != -1) return d[i][j];        if (!i && !j) return d[i][j] = x + a[i][j];        if (!i) return d[i][j] = dfs(i, j - 1, x) > 0 ? dfs(i, j - 1, x) + a[i][j] : -INF;        if (!j) return d[i][j] = dfs(i - 1, j, x) > 0 ? dfs(i - 1, j, x) + a[i][j] : -INF;        int t1 = dfs(i - 1, j, x);        int t2 = dfs(i, j - 1, x);        if (t1 > 0 || t2 > 0) d[i][j] = max(t1, t2) + a[i][j];        else d[i][j] = -INF;        return d[i][j];    }    bool judge(int x) {        memset(d, -1, sizeof(d));        return dfs(m - 1, n - 1, x) > 0;    }    int calculateMinimumHP(vector<vector<int>>& g) {        a = g;        m = a.size();        if (!m) return 0;        n = a[0].size();        int L = 1, R = INT_MAX, M = L + (R - L) / 2;        while (L < R) {            if (R == L + 1) {                if (judge(L)) M = L;                else M = R;                break;                } else {                M = L + (R - L) / 2;                if (judge(M)) R = M;                else L = M;            }        }        return M;    }};//algorithm 2const int maxn = 1005;#define INF 0x3e3e3e3eclass Solution {public:    int d[maxn][maxn];    int calculateMinimumHP(vector<vector<int>>& a) {        int m = a.size();        if (!m) return 0;        int n = a[0].size();        d[m - 1][n - 1] = a[m - 1][n - 1] > 0 ? 1 : -a[m - 1][n - 1] + 1;        for (int i = m - 2; i >= 0; i--) d[i][n - 1] = max(1, d[i + 1][n - 1] - a[i][n - 1]);        for (int j = n - 2; j >= 0; j--) d[m - 1][j] = max(1, d[m - 1][j + 1] - a[m - 1][j]);        for (int i = m - 2; i >= 0; i--) {            for (int j = n - 2; j >= 0; j--) {                d[i][j] = max(1, min(d[i + 1][j], d[i][j + 1]) - a[i][j]);            }        }        return d[0][0];    }};
0 0
原创粉丝点击