UVALive 5983 MAGRID DP

题意:在一个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)。|s[i][j]| < 1000,n,m < 500。

解法:这道题不能直接dp,否则会错。必须要先二分x的值,然后再dp。dp[i][j]记录的是走到(i,j)格所能有的最大生命值,但是要注意,d[i][j]只能在d[i][j-1]或d[i-1][j]中有一个为正时才能转移过来。

 

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
int dp[1000][1000];
int sum[1000][1000];
const int inf=999999999;
int main(){
   int t;
   scanf("%d",&t);
   while(t--){
    memset(dp,0,sizeof(dp));
    for(int i=0;i<=999;i++)
        for(int j=0;j<=999;j++)
        sum[i][j]=inf;
    int n,m;
    scanf("%d%d",&n,&m);
    int ans=0;
    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++)
            scanf("%d",&dp[i][j]);
    }
    sum[n][m]=1;
   for(int i=n;i>=1;i--){
        for(int j=m;j>=1;j--){

           sum[i-1][j]=min(sum[i-1][j],sum[i][j]-dp[i-1][j]);
           if(sum[i-1][j]<=0)
           sum[i-1][j]=1;

           sum[i][j-1]=min(sum[i][j-1],sum[i][j]-dp[i][j-1]);
           if(sum[i][j-1]<=0)
           sum[i][j-1]=1;
           /* if(i==1){
                dp[i][j]+=dp[i][j-1];
                if(dp[i][j]<=0){
                    sum[i+j]=min(sum[i+j],-dp[i][j]+1);
                    dp[i][j]=1;
                }
            }
            else if(j==1){
                dp[i][j]+=dp[i-1][j];
                if(dp[i][j]<=0){
                     sum[i+j]=min(sum[i+j],-dp[i][j]+1);
                     dp[i][j]=1;
                     }
            }
            else{
                  dp[i][j]+=max(dp[i-1][j],dp[i][j-1]);
             */

            }

        }




    printf("%d\n",sum[1][1]);
   }
   return 0;
}

 

posted @ 2015-08-22 11:51  柳下_MBX  阅读(331)  评论(0编辑  收藏  举报