与dp11相比,计算到达终点的最大值的同时,还需要记录路径上的最小值。

#include <iostream>

using namespace std;

int n, m;
int dp[1005][1005];    //骑士到达[i,j]时的最大血量
int ans[1005][1005];    //骑士到达[i,j]时路径上的最低血量

int main(){
    int val;
    
    cin >> n >> m;
    for(int i = 0; i < n; ++i){
        for(int j = 0; j < m; ++j){
            cin >> val;
            if(i == 0 && j == 0)
                ans[i][j] = dp[i][j] = val;
            else if(i == 0){
                dp[i][j] = dp[i][j-1] + val;
                ans[i][j] = min(ans[i][j-1], dp[i][j]);
            }
            else if(j == 0){
                dp[i][j] = dp[i-1][j] + val;
                ans[i][j] = min(ans[i-1][j], dp[i][j]);
            }
            else {
                dp[i][j] = max(dp[i-1][j], dp[i][j-1]) + val;
                if(dp[i][j] == dp[i-1][j]+val)
                    ans[i][j] = min(ans[i-1][j], dp[i][j]);
                else ans[i][j] = min(ans[i][j-1], dp[i][j]);
            }
        }
    }
    if(n == 1 || m == 1)//只有一条路径
        cout << max(0, -ans[n-1][m-1])+1;//血量最低为1
    else{//到达最后一点时,只能由[n-1][m]或[n][m-1]到达
        //选择两条路径中最大的最少血量,与到达终点时的血量中选出最小值
      	//与计算dp正好相反
        int res = max(ans[n-2][m-1], ans[n-1][m-2]);
        if(res == ans[n-2][m-1])
            res = min(dp[n-2][m-1]+val, res);
        else res = min(dp[n-1][m-2]+val, res);
        cout << max(0, -res)+1;
    }
    
    
    return 0;
}