Sample Output
37
2.题意
老鼠每次只能走k步停下来,停下的这个位置只能比上一个停留的位置大,并获取其价值,每次只能水平或垂直走,问最大能得到的价值在n*n的格子上,每个点各有若干块奶酪,胖老鼠从左上角出发,每次最多走k步(只能直走),且下一点必须比这一点的奶酪多,问最多能吃到多少块奶酪。
3.思路
记忆化搜索
虽然本质上是DFS这种搜索的思路,但其对搜索过的状态进行记录,从而完成对未知状态的推导,实际上也是一种DP的思想。
链接: 记忆化搜索专题.
4.代码
#define _CRT_SECURE_NO_WARNINGS
#include
#include
#include
#include
using namespace std;
const int maxn = 100 + 5;
int a[maxn][maxn], dp[maxn][maxn]; //dp[i][j]表示以第i行第j列个网格为起点所能得到的最大值
int dirt[4][2] = { {0,1},{0,-1},{1,0},{-1,0} }; ///四个方向
int n, k;
bool in(int x, int y) 判断是否出边界
{
if (x >= 0 && x < n&&y >= 0 && y < n)
return 1;
else
return 0;
}
int dfs(int x, int y)
{
int ans=0;
for (int j = 1; j <= k; j++) ///水平或者垂直方向走k步
{
for (int i = 0; i < 4; i++)
{
int nx = x + dirt[i][0]*j; ///水平
int ny = y + dirt[i][1]*j; ///垂直
if (!in(nx, ny)) continue;
if (a[x][y] >= a[nx][ny]) continue; //满足递增序列
if (dp[nx][ny]) //如果已经探索过了,就没必要继续深搜了
{
ans = max(ans, dp[nx][ny]); continue;
}
ans = max(ans, dfs(nx,ny)); //取所有的最大值
}
}
return dp[x][y] = a[x][y] + ans;
}
int main()
{
while(scanf(“%d%d”, &n, &k) != EOF)
{
memset(dp, 0, sizeof(dp));
if (n == -1 && k == -1) break;
for (int i = 0; i < n; i++)
for (int j = 0; j < n; j++)
scanf(“%d”, &a[i][j]);
printf(“%d\n”, dfs(0, 0)); //最优解在出发点上
}
return 0;
}
参考博客:
链接: 点击这里.