解题思路

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

  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))

算法及复杂度

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