跳到主要内容

地下城题库

地下城游戏

一些恶魔抓住了公主(P)并将她关在了地下城的右下角。地下城是由 M x N 个房间组成的二维网格。我们英勇的骑士(K)最初被安置在左上角的房间里,他必须穿过地下城并通过对抗恶魔来拯救公主。

骑士的初始健康点数为一个正整数。如果他的健康点数在某一时刻降至 0 或以下,他会立即死亡。

有些房间由恶魔守卫,因此骑士在进入这些房间时会失去健康点数(若房间里的值为负整数,则表示骑士将损失健康点数);其他房间要么是空的(房间里的值为 0),要么包含增加骑士健康点数的魔法球(若房间里的值为正整数,则表示骑士将增加健康点数)。

为了尽快到达公主,骑士决定每次只向右或向下移动一步。

编写一个函数来计算确保骑士能够拯救到公主所需的最低初始健康点数。

方案 动态规划

思路: 对于M*N的网格每次只能向右或者向下移动一步的题型场景,可以用动态规划,并且是从右下往左上进行动态规划

  1. 状态定义: dp[i][j]表示从坐标(i,j)到终点所需的最小初始值。换句话说,当我们到达坐标(i,j)时,如果此时我们的路径和不小于dp[i][j],我们就能到达终点
  2. 状态转移方程:对于dp[i][j],我们只要关心dp[i][j+1]dp[i+1][j]的最小值min,记当前格子的值为dungeon(i,j),那么在坐标(i,j)的初始值只要达到min-dungecon(i,j)即可。同时初始值还必须大于等于1,可得状态转移方程为:dp[i][j]=max(min(dp[i+1][j],dp[i][j+1])-dungecon(i,j),1)
  3. 初始化状态: 当i=row-1或者j=col-1时,此时的dp[i][j+1]dp[i+1][j]有无效值
  • dp 初始元素为极大值
  • dp[row][col-1]=1
  • dp[row-1][col]=1
  1. 问题答案: 最终答案为dp[0][0]

:::details 点击查看代码

function calculateMinimumHP(dungeon) {
const row=dungeon.length;
const col=dungeon[0].length;
const dp=new Array(row+1).fill(0).map(()=>new Array(col+1).fill(Infinity))
dp[row][col-1]=1;
dp[row-1][col]=1;
for(let i=row-1;i>=0;i--){
for(let j=col-1;j>=0;j--){
dp[i][j]=Math.max(Math.min(dp[i+1][j],dp[i][j+1])-dungeon[i][j],1);
}
}
return dp[0][0];
};

:::

性能分析:

  • 时间复杂度: O(row*col)
  • 空间复杂度: O(row*col)