问题描述
FatMouse在一个城市中存储了一些奶酪。可以将城市视为尺寸为n的正方形网格:每个网格位置都标记为(p,q),其中0 <= p <n和0 <= q <n。在每个网格位置,Fatmouse都在一个洞中隐藏了0到100块奶酪。现在,他将享受他最喜欢的食物。
FatMouse首先站在位置(0,0)。他吃掉了他站立的奶酪,然后水平或垂直跑到另一个位置。问题在于,有一只名为Top Killer的超级猫坐在他的洞附近,因此每次他最多可以跑k个位置进入洞中,然后再被Top Killer抓住。更糟糕的是-在一个地方吃完奶酪后,FatMouse变得更胖。因此,为了获得足够的能量进行下一次跑步,他必须跑到一个位置,那里的奶酪块比当前洞中的奶酪块多。
给定n,k和每个网格位置处的奶酪块数,请计算FatMouse在无法移动之前可以食用的最大奶酪量。
输入值
有几个测试用例。每个测试用例由一行包含两个介于1和100之间的整数的行组成:n和kn行,每个行都有n个数字:第一行包含位置(0,0)(0,1)处的奶酪块数。 (0,n-1); 下一行包含在(1,0),(1,1),…(1,n-1)等位置的奶酪块数。输入以一对-1结尾。
输出量
对于一行中的每个测试用例输出,单个整数给出收集的奶酪块数。
样本输入
3 1
1 2 5
10 11 6
12 12 7
-1 -1
样本输出
37
资源
浙江大学训练比赛2001
- 需要通过记忆化保存每个点的最优解
- 下次递归就可以直接调用
#include<bits/stdc++.h>
using namespace std;
int n, k;
int a[1000][1000];
int dp[1000][1000];
int dir[4][2] = {{0,1},{1,0},{-1,0},{0,-1}};
int dfs(int x, int y){
int ans = 0;
if(dp[x][y]) return dp[x][y];
for(int i = 0; i < 4; i ++){
for(int j = 1; j <= k; j ++){
int tx = x + dir[i][0] * j;
int ty = y + dir[i][1] * j;
if(tx < 0 || ty < 0 || tx > n - 1 || ty > n - 1)continue;
if(a[tx][ty] < a[x][y])continue;
ans = max(ans,dfs(tx, ty));
}
}
dp[x][y] = ans + a[x][y];
return dp[x][y];
}
int main(){
ios::sync_with_stdio(false);
while(cin >> n >> k){
if(n == -1 && k == -1)break;
memset(dp,0,sizeof(dp));
for(int i = 0; i < n; i ++)
for(int j = 0; j < n; j ++)
cin >> a[i][j];
dfs(0,0);
cout << dp[0][0] << endl;
}
}