/********************************************************************************************
*description:龙与地下城游戏
* 给定一个二维数组map,表示一张地图,
* 骑士从左上角出发,每次只能向右或向下走,最后到达右下角见到公主
* map每个位置数字,正数代表加血,负数代表有怪兽减血,骑士血量不能少于1
* 为保证骑士能见到公主,初始血量最少是多少?
*******************************************************************************************/
#include<iostream>
#include<vector>
using namespace std;
//方法:时间复杂度O(M*N),空间复杂度O(M*N)
//经典动态规划问题,创建与map同大的二维数组dp[M][N]
//dp[i][j]代表骑士走上[i,j]位置且从该位置走到右下角需要的最低血量,最终需要的结果是dp[0][0]
//dp[M-1][N-1],骑士走上最终位置需要的最低血量=
// 1,当map[M-1][N-1]>=0
// 1-map[M-1][N-1],当map[M-1][N-1]<0
//dp[M-1][j]最后一行=max(1, dp[M-1][j+1]-map[M-1][j]
//dp[i][N-1]最后一列=max(1, dp[i+1][N-1]-map[i][N-1]
//dp[i][j]:取两项最小值,从右往左从下往上遍历
// 1.max(1,dp[i-1][j]-map[i][j])
// 2.max(1,dp[i][j-1]-max[i][j])
//得到dp之后,右下角元素即为结果。
int minBlood(vector<vector<int>> map)
{
int M = map.size();
int N = map[0].size();
vector<vector<int>> dp(M, N);
if (map[M-1][N-1] >= 0)
dp[M-1][N-1] = 1;
else
dp[M-1][N-1] = 1-map[M-1][N-1];
for (int j = N-2; j >= 0; j--)
dp[M-1][j] = dp[M-1][j+1] - map[M-1][j] > 1 ? dp[M-1][j+1] - map[M-1][j] : 1;
for (int i = M-2; i >= 0; i--)
dp[i][N-1] = dp[i+1][N-1] - map[i][N-1] > 1 ? dp[i+1][N-1] - map[i][N-1] : 1;
for (int i = M-2; i >= 0; i--)
{
for (int j = N-2; j >= 0; j--)
{
int val1 = dp[i+1][j]-map[i][j] > 1 ? dp[i+1][j]-map[i][j] : 1;
int val2 = dp[i][j+1]-map[i][j] > 1 ? dp[i][j+1]-map[i][j] : 1;
dp[i][j] = val1 > val2 ? val2 : val1;
}
}
return dp[0][0];
}
int main_11()
{
vector<vector<int>> map;
int l1[3] ={ -2, -3, 3};
vector<int> line1(l1, l1+3);
int l2[3] ={ -5, -10, 1};
vector<int> line2(l2, l2+3);
int l3[3] ={ 0, 30, -5};
vector<int> line3(l3, l3+3);
map.push_back(line1);
map.push_back(line2);
map.push_back(line3);
cout << minBlood(map);
return 0;
}