题意: 一个n * n的二维图,从最左上角出发,一次最多水平或者竖直的走k步,然后经过比他大的点,求加上所有经过的权之后最大的值;
思路: 知道起点,但不知道终点,记忆化搜索的时候就是以这个点作为输出点,从后往前推;
PS:记忆化搜索的时候一定不能在中间改变dp的值,只能在最后改;
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
using namespace std;
typedef long long ll;
const ll maxn = 200 + 10;
#define INF 0x3f3f3f3f
ll a[maxn][maxn];
ll dp[maxn][maxn];
void Init()
{
memset(dp,-1,sizeof(dp));
}
ll derict[][2] =
{
-1,0,
1,0,
0,1,
0,-1
};
ll n,k;
ll work(ll x,ll y)
{
if(dp[x][y] != -1)
return dp[x][y];
ll maxs =0;
for(ll i = 1; i <= k; i ++)
{
for(ll j = 0; j < 4; j ++)
{
ll xx = x + derict[j][0] * i,yy = y + derict[j][1] * i;
if(xx >= 1 && xx <= n && yy >= 1 && yy <= n && a[x][y] < a[xx][yy])
{
maxs = max(maxs,work(xx,yy));
}
}
}
return dp[x][y] = maxs + a[x][y];
}
int main()
{
while( ~ scanf("%I64d%I64d",&n,&k))
{
if(n == -1 && k == -1)
break;
Init();
for(ll i = 1; i <= n; i ++)
{
for(ll j = 1; j <= n; j ++)
{
scanf("%I64d",&a[i][j]);
}
}
ll ans = work(1,1);
cout << ans << endl;
}
return 0;
}