Uva 10913 - Walking on a Grid 记忆搜索

题意:给出一个n*n的方阵,要求从(1,1)出发到点(n,n)的一条路径,并且经过的点的值为负数的个数小于等于k,输出路径上点的值之和最大值,若无法达到终点,则输出impossible

思路:定义四维数组f[i][j][num][v],表示在点i,j处用了k个负数从v方向来的路径之和最大值

v=0表示从上面来,那么可以往下、左、右递归,v=1表示从左边来,可以向下、右递归,v=2表示从右边来,可以向左、向下递归

代码:

#include <iostream>
#include <stdio.h>
#include <cmath>
#include <algorithm>
#include <cstring>
using namespace std;
#define inf -200000000
long long f[80][80][8][3];
bool vis[80][80][8][3];//0为从上面来,1为从左边来,2为从右边来
int a[80][80];
int n,k;
long long Max(long long  x,long long y,long long z)
{
    if(x>=y && x>=z)return x;
    else if(y>=x && y>=z)return y;
    else
        return z;
}
long long DP(int i,int j,int num,int v)
{
    int kk;
    long long x,y,z,mmax;
    if(vis[i][j][num][v])
        return f[i][j][num][v];
        vis[i][j][num][v]=1;

    if(num==k && a[i][j]<0)//大于所给k,那么直接不能到达,所以inf
        return f[i][j][num][v]=inf;
    if(i==n && j==n)
        return f[i][j][num][v]=a[i][j];
    if(a[i][j]<0)
        kk=num+1;
    else
        kk=num;
    if(v==0)
    {
        x=y=z=inf;
        if(i<n)
            x=DP(i+1,j,kk,0);
        if(j>1)
            y=DP(i,j-1,kk,2);
        if(j<n)
            z=DP(i,j+1,kk,1);

        mmax=Max(x,y,z);
        if(mmax!=inf && mmax+a[i][j]>f[i][j][num][v])
            f[i][j][num][v]=mmax+a[i][j];
    }
    else if(v==1)
    {
        x=y=z=inf;
        if(i<n)
            x=DP(i+1,j,kk,0);
        if(j<n)
            y=DP(i,j+1,kk,1);

        mmax=Max(x,y,z);
        if(mmax!=inf && mmax+a[i][j]>f[i][j][num][v])
            f[i][j][num][v]=mmax+a[i][j];
    }
    else
    {
        x=y=z=inf;
        if(i<n)
            x=DP(i+1,j,kk,0);
        if(j>1)
            y=DP(i,j-1,kk,2);

        mmax=Max(x,y,z);
        if(mmax!=inf && mmax+a[i][j]>f[i][j][num][v])
            f[i][j][num][v]=mmax+a[i][j];
    }
    return f[i][j][num][v];
}
void solve(int g)
{
    for(int i=1; i<=n; i++)
        for(int j=1; j<=n; j++)
            for(int num=0; num<=k; num++)
                for(int v=0; v<=2; v++)
                    f[i][j][num][v]=inf;//定义为最小的
    memset(vis,0,sizeof(vis));
    long long ans;
    ans=DP(1,1,0,0);
    if(ans!=inf)
        printf("Case %d: %lld\n",g,ans);
    else
        printf("Case %d: impossible\n",g);
}
int main()
{
    int g=0;
    while(scanf("%d%d",&n,&k)!=EOF)
    {
        if(!n && !k)break;
        g++;
        for(int i=1; i<=n; i++)
            for(int j=1; j<=n; j++)
                scanf("%d",&a[i][j]);
        solve(g);
    }
    return 0;
}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值