动态规划题型总结 (三)

类型五 (自底向上)

① 地下城游戏: link

一些恶魔抓住了公主(P)并将她关在了地下城的右下角。地下城是由 M x N 个房间组成的二维网格。我们英勇的骑士(K)最初被安置在左上角的房间里,他必须穿过地下城并通过对抗恶魔来拯救公主。
骑士的初始健康点数为一个正整数。如果他的健康点数在某一时刻降至 0 或以下,他会立即死亡。
有些房间由恶魔守卫,因此骑士在进入这些房间时会失去健康点数(若房间里的值为负整数,则表示骑士将损失健康点数);其他房间要么是空的(房间里的值为 0),要么包含增加骑士健康点数的魔法球(若房间里的值为正整数,则表示骑士将增加健康点数)。
为了尽快到达公主,骑士决定每次只向右或向下移动一步。
编写一个函数来计算确保骑士能够拯救到公主所需的最低初始健康点数。
例如,考虑到如下布局的地下城,如果骑士遵循最佳路径 右 -> 右 -> 下 -> 下,则骑士的初始健康点数至少为 7。
动态规划题型总结 (三)

-2 (min(6-[-2],5-[-2])=7 -3 (min(11-[-3],2-[-3])=5) 3(5-3=2
-5 (min(1-[-5],11-[-5])=6) -10(min(1-[-10],5-[-10])=11 1(6-1=5
10(1-10<0 → 1 30(6-30<0 → 1 -5 (1-[-5]=6

分析: dp[i][j]用来表示到达第(i,j)个格子时需要的健康点数,从右下角开始向左上角分析,计算到最左上角即为所需的健康点数
若第(i,j)个格子内的数字小于等于零,则dp[i][j]至少为1才可能继续往下走
若第(i,j)个格子内的数字大于零,那么dp[i][j]所需的点数为dp[i+1][j],dp[i][j+1]中的最小值减去第(i,j)个格子内的数字,即:min(dp[i+1][j],dp[i][j+1])-dungeon[i][j]

初始值 :
判断右下角格子内的数字dungeon[m-1][n-1]是否小于等于0;
–> 若dungeon[m-1][n-1] > 0,则到达右下角的时候健康点数至少为1就够了(若小于1,在半路上就死掉了)
–> 若dungeon[m-1][n-1] <= 0,那么到达右下角的时候健康点数至少为1-dungeon[m-1][n-1]

边界条件:(最左边和最下边)
dp[i+1][n-1] - dungeon[i][n-1] 和 dp[m-1][i+1] - dungeon[m-1][i] 是否小于等于0;
如果小于等于0,则所需点数至少为1;
如果大于0,则所需点数为dp[i+1][n-1] - dungeon[i][n-1] 和 dp[m-1][i+1] - dungeon[m-1][i]

    int min(int a, int b)
    {
        return a<b?a:b;
    }
    int calculateMinimumHP(vector<vector<int>>& dungeon) {
        int m = dungeon.size(),n = dungeon[0].size();
        vector<vector<int>>dp(m,vector<int>(n,0));
        int minhel = dp[0][0];
        int res = 0;
        dp[m-1][n-1] = dungeon[m-1][n-1] <= 0 ? 1-dungeon[m-1][n-1] : 1;
        for(int i = m-2;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--)
            {
                dp[i][j] = min(dp[i+1][j],dp[i][j+1])-dungeon[i][j] <=0 ?  1:min(dp[i+1][j],dp[i][j+1])-dungeon[i][j];
            }
        }
        return dp[0][0];
    }
上一篇:[CF118E] Bertown roads - Tarjan


下一篇:CF671D Roads in Yusland