UVALive 5983 MAGRID (二分 + dp)

题目

UVALive 5983 MAGRID

题意

从左上角走到右下角,每次只能往右或者往下走一步,每个格子有一个值,值为负代表体力消耗,为正表示体力上升,当体力小于等于0时死亡,问为了走到右下角时不死,初始最小体力为多少

解法

  • 正向

二分答案 + dp验证
dp[i][j] 表示在第i行,第j列能够剩余最大体力


dp[1][1] = mid;
for(int i = 1; i <= r; i++) {
    for(int j = 1; j <= c; j++) {
        if(i == 1 && j == 1) {
            continue;
        }
        dp[i][j] = max(dp[i - 1][j], dp[i][j - 1]) + val[i][j];
        if(dp[i][j] <= 0) {
            dp[i][j] = -INF;
        }
    }
}

  • 反向

好神奇,还不知道为什么对。。。


for(int i = 0; i <= n; i++)
    dp[i][m] = INF;
for(int i = 0; i <= m; i++)
    dp[n][i] = INF;
dp[n - 1][m] = dp[n][m - 1] = 1;
for(int i = n - 1; i >= 0; i--) {
    for(int j = m - 1; j >= 0; j--) {
        dp[i][j] = min(dp[i + 1][j], dp[i][j + 1]) - val[i][j];
        if(dp[i][j] <= 1)
            dp[i][j] = 1;
    }
}

代码

//正向
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 505;
const int INF = 0x3f3f3f3f;
int dp[N][N];
int val[N][N];
int r, c;
int check(int mid) {
    dp[1][1] = mid;
    for(int i = 1; i <= r; i++) {
        for(int j = 1; j <= c; j++) {
            if(i == 1 && j == 1)
                continue;
            dp[i][j] = max(dp[i - 1][j], dp[i][j - 1]) + val[i][j];
            if(dp[i][j] <= 0)
                dp[i][j] = -INF;
        }
    }
    return dp[r][c] > 0;
}
int main() {
    int T;
    scanf("%d", &T);
    while(T--) {
        scanf("%d %d", &r, &c);
        for(int i = 1; i <= r; i++) {
            for(int j = 1; j <= c; j++)
                scanf("%d", &val[i][j]);
        }
        for(int i = 1; i <= r; i++)
            dp[i][0] = -INF;
        for(int i = 1; i <= c; i++)
            dp[0][i] = -INF;
        int low = 1, high = INF;
        while(low <= high) {
            int mid = (low + high) / 2;
            if(check(mid))
                high = mid - 1;
            else
                low = mid + 1;
        }
        printf("%d\n", low);
    }
}
//反向
#include <cstdio>
#include <algorithm>
using namespace std;
const int N = 505;
const int INF = 0x3f3f3f3f;
int dp[N][N];
int val[N][N];
int main() {
    int T;
    int n, m;
    scanf("%d", &T);
    while(T--) {
        scanf("%d %d", &n, &m);
        for(int i = 0; i < n; i++) {
            for(int j = 0; j < m; j++)
                scanf("%d", &val[i][j]);
        }
        for(int i = 0; i <= n; i++)
            dp[i][m] = INF;
        for(int i = 0; i <= m; i++)
            dp[n][i] = INF;
        dp[n - 1][m] = dp[n][m - 1] = 1;
        for(int i = n - 1; i >= 0; i--) {
            for(int j = m - 1; j >= 0; j--) {
                dp[i][j] = min(dp[i + 1][j], dp[i][j + 1]) - val[i][j];
                if(dp[i][j] <= 1)
                    dp[i][j] = 1;
            }
        }
        printf("%d\n", dp[0][0]);
    }
    return 0;
}

Source

Regionals 2011 Asia - Amritapuri

posted @ 2015-08-24 20:36  ACM_Record  阅读(131)  评论(0编辑  收藏  举报