有如下规则:你只有三个方向,左、右、下。不能走出方格。一个方格只能走一次。你要保证你的路径上的格子的和最大。你最多只能走k(最多为5)个负权值的格子,从起点到终点。
要注意,因为可以向右走,所以定义三维状态可能有问题,所以定义了四维,表示从当前点向左右下走能得到的最大的值。
#include <iostream> #include <cstring> #include <cstdio> using namespace std; #define LL long long #define INF -((LL)1<<60) const int N=80; LL data[N][N],map[N][N][7][3]; bool vis[N][N][7][3],grid[N][N]; int n,dir[3][2]={{0,1},{1,0},{0,-1}}; bool check(int,int); LL dp(int,int,int,int); int main() { int k,t_cnt=0; while(scanf("%d%d",&n,&k)!=EOF) { if(n==0&&k==0) break; memset(vis,0,sizeof(vis)); memset(grid,0,sizeof(grid)); for(int i=1;i<=n;i++) { for(int j=1;j<=n;j++) scanf("%lld",&data[i][j]); } if(data[n][n]<0) k--; LL res=dp(1,1,k+1,1); printf("Case %d: ",++t_cnt); if(res!=INF) printf("%lld\n",res); else puts("impossible"); } return 0; } LL dp(int x,int y,int z,int r) { bool &flag=vis[x][y][z][r]; LL &res=map[x][y][z][r]; if(flag) return res; else if((x==n&&y==n)||z==0) { flag=1; if(z==0) res=INF; else res=data[x][y]; return res; } else { res=INF; for(int i=0;i<3;i++) { int xx=x+dir[i][0],yy=y+dir[i][1],t=0; if(data[x][y]<0) t=-1; if(check(xx,yy)&&!grid[xx][yy]) { if((r==0&&i==2)||(r==2&&i==0)) continue; grid[xx][yy]=1; LL temp=dp(xx,yy,z+t,i); if(temp!=INF) res=max(res,temp+data[x][y]); grid[xx][yy]=0; } } flag=1;return res; } } bool check(int x,int y) { return x>=1&&x<=n&&y>=1&&y<=n; }