Uva 10913 - Walking on a Grid 记忆搜索

来源:互联网 发布:淘宝十年产品事 百度云 编辑:程序博客网 时间:2024/05/16 17:29

题意:给出一个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 -200000000long 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;}