题目链接 : http://www.spoj.com/problems/AMR11A/
题目大意:给出一个r * c大小的方格二维图,走到每个方格上需要加上上面的值,从左上角开始走,
规定只能往下右两个方向,要求全程值都大于零,求最开始最小值。
分析:倒着dp,开一个二维数组dp[r][c],dp[i][j]表示走到i, j位置所需最小值,可以得到初等关系:
DP[I][J]+MAP[I][J]=DP[I+1][J]或者DP[I][J+1]
移项,同时注意到每一步最小值为 1,可得:
DP[I][J]=MAX{1,MIN { DP[I+1][J] , DP[I][J+1] } - MAP[I][J] };
(注意要分情况在边界的时候,以防越界)
代码如下:
#include <iostream>
#include <cstring>
#include <string>
#include <cstdio>
#include <algorithm>
#include <cstdlib>
#include <ctype.h>
#include <cmath>
#include <stack>
#include <queue>
#include <sstream>
#include <set>
#include <map>
#include <vector>
#include <limits.h>
using namespace std;
typedef long long ll;
const int N = 500 + 10;
int grid[N][N];
int dp[N][N];
int r, c, t;
void DP(){
dp[r][c] = 1;
for(int i = r; i > 0; i--){
for(int j = c; j > 0; j--){
if(i == r && j == c){
dp[i][j] = 1;
}else if(i == r){
dp[i][j] = max(1, dp[i][j+1] - grid[i][j]);
}else if(j == c){
dp[i][j] = max(1, dp[i+1][j] - grid[i][j]);
}else{
dp[i][j] = max(1, min(dp[i][j+1], dp[i+1][j]) - grid[i][j]);
}
}
}
}
int main(){
cin >> t;
while(t--){
cin >> r >> c;
for(int i = 1; i <= r; i++){
for(int j = 1; j <= c; j++){
cin >> grid[i][j];
}
}
DP();
printf("%d\n", dp[1][1]);
}
}