Walking on a Grid - UVa 10913 dp

4th IIUC Inter-University Programming Contest, 2005

I

Walking on a Grid

Input: standard input
Output: standard output

Problemsetter: Sohel Hafiz

You will be given a square grid of size N × N. The top-left square has a coordinate of (1, 1) and that of bottom-right is (N, N). Your job is to walk from (1, 1) to (N, N). Very easy, right? That’s why you have to follow some rules when walking.

  1. You can only move left, right or down.
  2. (i, j-1) is left of (i, j), (i, j+1) is right of (i, j) and (i+1, j) is down of (i, j).
  3. You can never move outside the grid.
  4. You can not step on a cell more than once.
  5. Every cell has an integer associated with it.
  6. You have to make sure the sum of integers of the path is maximized.
  7. You can step on at most negative integers from source to destination.

Input

Each case will start with two integers N and kN ≤ 75 and k ≤ 5. Each of the next N lines will contain Nintegers each given in row major order. That is, the first integer of the first row is (1, 1) and the last integer of last row is (N, N). Input terminates with two zeros on a line.

Output

For every case output the case number. If it’s not possible to reach the destination meeting the above rules then output “impossible”, else print the maximum sum of integers of the path.

Sample Input

Output for Sample Input

4 1
1 2 3 -5
-10 6 0 -1
-10 -10 -10 2
0 0 0 1
4 0
1 2 3 -5
-10 6 0 -1
-10 -10 -10 2
0 0 0 1
0 0

Case 1: 11
Case 2: impossible


题意:从左上角开始走,最后要走到右下角,每次只能往下,往左,往右走,不能重复走到一个格子上,并且路径中负数的情况不能超过k,问最大的路径和是多少。

思路:dp[i][j][k][0-1]表示当前在i行j列时,已经经过k个负数,且可以继续往左(右)的最大路径和。

AC代码如下:

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int dp[110][110][10][2],num[110][110],sum[110][110],n,m,INF=1000000000;
void getleft(int i,int y)
{ int j,k;
  for(j=y-1;j>=1;j--)
  { if(num[i][j]>=0)
    { for(k=0;k<=m;k++)
       dp[i][j][k][0]=max(dp[i][j][k][0],dp[i][j+1][k][0]+num[i][j]);
    }
    else
    { for(k=0;k<=m;k++)
       dp[i][j][k+1][0]=max(dp[i][j][k+1][0],dp[i][j+1][k][0]+num[i][j]);
    }
  }
}
void getright(int i,int y)
{ int j,k;
  for(j=y+1;j<=n;j++)
  { if(num[i][j]>=0)
    { for(k=0;k<=m;k++)
       dp[i][j][k][1]=max(dp[i][j][k][1],dp[i][j-1][k][1]+num[i][j]);
    }
    else
    { for(k=0;k<=m;k++)
       dp[i][j][k+1][1]=max(dp[i][j][k+1][1],dp[i][j-1][k][1]+num[i][j]);
    }
  }
}
int main()
{ int i,j,k,p,ans,t=0,ret;
  while(~scanf("%d%d",&n,&m) && n+m)
  { for(i=1;i<=n;i++)
     for(j=1;j<=n;j++)
      scanf("%d",&num[i][j]);
    for(i=0;i<=n;i++)
     for(j=0;j<=n;j++)
      for(k=0;k<=m;k++)
      { dp[i][j][k][0]=-1000000000;
        dp[i][j][k][1]=-1000000000;
      }
    dp[1][0][0][1]=0;
    getright(1,0);
    for(i=2;i<=n;i++)
     for(j=1;j<=n;j++)
     { for(k=0;k<=m;k++)
        if(num[i][j]>=0)
        { ret=max(dp[i-1][j][k][0]+num[i][j],dp[i-1][j][k][1]+num[i][j]);
          dp[i][j][k][0]=max(dp[i][j][k][0],ret);
          dp[i][j][k][1]=max(dp[i][j][k][1],ret);
        }
        else
        { ret=max(dp[i-1][j][k][0]+num[i][j],dp[i-1][j][k][1]+num[i][j]);
          dp[i][j][k+1][0]=max(dp[i][j][k+1][0],ret);
          dp[i][j][k+1][1]=max(dp[i][j][k+1][1],ret);
        }
        getleft(i,j);
        getright(i,j);
     }
    ans=-1000000000;
    for(i=0;i<=m;i++)
    { if(dp[n][n][i][1]>-100000000)
      ans=max(ans,dp[n][n][i][1]);
    }
    if(ans<=-100000000)
     printf("Case %d: impossible\n",++t);
    else
     printf("Case %d: %d\n",++t,ans);
  }
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值