UVALive 5983 MAGRID(二分+dp)

題目鏈接:http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=26401


題意:在一個n*m的網格上,從(0,0)走到(n-1,m-1),每次只能向右或者向下走一格。一個人最初有一個生命值x,走到每一個格生命值會變爲x + s[i][j],(s[i][j]可爲負,0,正),若生命值小於等於0,則人死亡。告訴網格上所有s[i][j],求x的最小值使得該人能夠或者走到(n-1,m-1)。

題解:二分生命值,再dp。類似數塔。

#include<cstring>
#include<algorithm>
#include<cstdio>
#include<iostream>
using namespace std;

const int N=520;
const int inf=99999999;

int a[N][N],dp[N][N];
int n,m;

int C(int fir) {
    dp[1][1]=fir;
    for(int i=1; i<=n; i++) {
        for(int j=1; j<=m; j++) {
            if(i==1&&j==1)continue;
            if(i==1) {
                if(dp[i][j-1]>0) {
                    if(a[i][j]+dp[i][j-1]<=0)dp[i][j]=-inf;
                    else  dp[i][j]=a[i][j]+dp[i][j-1];
                } else dp[i][j]=-inf;
            } else if(j==1) {
                if(dp[i-1][j]>0) {
                    if(a[i][j]+dp[i-1][j]<=0)dp[i][j]=-inf;
                    else  dp[i][j]=a[i][j]+dp[i-1][j];
                } else dp[i][j]=-inf;
            } else {
                if(dp[i][j-1]>0) {
                    if(a[i][j]+dp[i][j-1]<=0)dp[i][j]=-inf;
                    else  dp[i][j]=a[i][j]+dp[i][j-1];
                } else dp[i][j]=-inf;
                if(dp[i-1][j]>0) {
                    if(a[i][j]+dp[i-1][j]>0)dp[i][j]=max(dp[i][j],a[i][j]+dp[i-1][j]);
                }
            }
        }
    }
    return dp[n][m];
}

int main() {
   // freopen("test.in","r",stdin);
    int t;
    cin>>t;
    while(t--) {
        scanf("%d%d",&n,&m);
        for(int i=1; i<=n; i++) {
            for(int j=1; j<=m; j++) {
                scanf("%d",&a[i][j]);
            }
        }
        int l=1,r=inf;
        while(l<r) {
            int mid=(l+r)/2;
            if(C(mid)>0)r=mid;
            else   l=mid+1;
        }
        printf("%d\n",r);
    }
    return 0;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章