题解 | 龙与地下城游戏问题

龙与地下城游戏问题

https://www.nowcoder.com/practice/c0ca4c9e65144af69ada03febaa0e33a

解题思路

这是一个动态规划问题,但需要从终点往起点推导:

  1. 创建一个 数组, 表示到达位置 时需要的最小血量
  2. 从右下角开始,逆向推导到左上角
  3. 对于每个位置
    • 如果是终点,则
    • 否则,
  4. 最终 就是所需的最小初始血量

代码

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

int minInitialHealth(vector<vector<int>>& map) {
    int n = map.size();
    int m = map[0].size();
    vector<vector<int>> dp(n, vector<int>(m));
    
    // 初始化终点
    dp[n-1][m-1] = max(1, 1 - map[n-1][m-1]);
    
    // 初始化最后一列
    for(int i = n-2; i >= 0; i--) {
        dp[i][m-1] = max(1, dp[i+1][m-1] - map[i][m-1]);
    }
    
    // 初始化最后一行
    for(int j = m-2; j >= 0; j--) {
        dp[n-1][j] = max(1, dp[n-1][j+1] - map[n-1][j]);
    }
    
    // 填充其他位置
    for(int i = n-2; i >= 0; i--) {
        for(int j = m-2; j >= 0; j--) {
            int minNext = min(dp[i+1][j], dp[i][j+1]);
            dp[i][j] = max(1, minNext - map[i][j]);
        }
    }
    
    return dp[0][0];
}

int main() {
    int n, m;
    cin >> n >> m;
    vector<vector<int>> map(n, vector<int>(m));
    
    for(int i = 0; i < n; i++) {
        for(int j = 0; j < m; j++) {
            cin >> map[i][j];
        }
    }
    
    cout << minInitialHealth(map) << endl;
    return 0;
}
import java.util.Scanner;

public class Main {
    public static int minInitialHealth(int[][] map) {
        int n = map.length;
        int m = map[0].length;
        int[][] dp = new int[n][m];
        
        // 初始化终点
        dp[n-1][m-1] = Math.max(1, 1 - map[n-1][m-1]);
        
        // 初始化最后一列
        for(int i = n-2; i >= 0; i--) {
            dp[i][m-1] = Math.max(1, dp[i+1][m-1] - map[i][m-1]);
        }
        
        // 初始化最后一行
        for(int j = m-2; j >= 0; j--) {
            dp[n-1][j] = Math.max(1, dp[n-1][j+1] - map[n-1][j]);
        }
        
        // 填充其他位置
        for(int i = n-2; i >= 0; i--) {
            for(int j = m-2; j >= 0; j--) {
                int minNext = Math.min(dp[i+1][j], dp[i][j+1]);
                dp[i][j] = Math.max(1, minNext - map[i][j]);
            }
        }
        
        return dp[0][0];
    }
    
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        int m = sc.nextInt();
        int[][] map = new int[n][m];
        
        for(int i = 0; i < n; i++) {
            for(int j = 0; j < m; j++) {
                map[i][j] = sc.nextInt();
            }
        }
        
        System.out.println(minInitialHealth(map));
        sc.close();
    }
}
def min_initial_health(map_grid):
    n, m = len(map_grid), len(map_grid[0])
    dp = [[0] * m for _ in range(n)]
    
    # 初始化终点
    dp[n-1][m-1] = max(1, 1 - map_grid[n-1][m-1])
    
    # 初始化最后一列
    for i in range(n-2, -1, -1):
        dp[i][m-1] = max(1, dp[i+1][m-1] - map_grid[i][m-1])
    
    # 初始化最后一行
    for j in range(m-2, -1, -1):
        dp[n-1][j] = max(1, dp[n-1][j+1] - map_grid[n-1][j])
    
    # 填充其他位置
    for i in range(n-2, -1, -1):
        for j in range(m-2, -1, -1):
            min_next = min(dp[i+1][j], dp[i][j+1])
            dp[i][j] = max(1, min_next - map_grid[i][j])
    
    return dp[0][0]

n, m = map(int, input().split())
map_grid = []
for _ in range(n):
    row = list(map(int, input().split()))
    map_grid.append(row)

print(min_initial_health(map_grid))

算法及复杂度

  • 算法:动态规划(逆向推导)
  • 时间复杂度:,需要遍历整个地图
  • 空间复杂度:,需要一个二维 数组
全部评论

相关推荐

不愿透露姓名的神秘牛友
昨天 12:20
点赞 评论 收藏
分享
06-15 02:05
已编辑
南昌航空大学 数据分析师
Eason三木:你如果想干技术岗,那几个发公众号合唱比赛的经历就去掉,优秀团员去掉,求职没用。然后CET4这种不是奖项,是技能,放到下面的专业技能里或者单独列一个英语能力。 另外好好改改你的排版,首行缩进完全没有必要,行间距好好调调,别让字和标题背景黏在一起,你下面说能做高质量PPT你得展现出来啊,你这简历排版我用PPT做的都能比你做的好。 然后自我评价,你如果要干数据工程师,抗压能力强最起码得有吧。
简历中的项目经历要怎么写
点赞 评论 收藏
分享
不愿透露姓名的神秘牛友
07-10 15:58
投个小米提前批试试水,先投一个岗位看看形势,不行就再沉淀一下投第二个岗位,莫辜负
Java抽象带篮子:我嘞个骚刚,已经开始研发6g了吗
投递小米集团等公司7个岗位
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务