刚学习了记忆化搜索,写了这篇博客记录一下。
先附上题目链接(这两道题是一道题)
POJ1088滑雪:
http://poj.org/problem?id=1088
Hrbust1179下山:
http://acm.hrbust.edu.cn/index.php?m=ProblemSet&a=showProblem&problem_id=1179
不知道从哪儿进入dfs,直接暴搜的话TLE,所以需要开一个数组记录每个点的最长路径,进行记忆化搜索,这样每搜索一个点时,如果这个点被搜索过,那么就可以直接拿结果来用,从而降低了时间复杂度。
更为详细的说明写在了注释。
代码如下:(以下为POJ的AC代码,Hrbust1179题还需要加上多组输入)
#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <algorithm>
#include <cmath>
#include <vector>
#include <map>
#include <set>
#include <iterator>
#define rep(i,a,b) for(int i=(a);i<=(b);i++)
#define per(i,a,b) for(int i=(a);i>=(b);i--)
#define ms(s, x) memset(s,x,sizeof(s))
#define pb push_back
#define inf 0x3f3f3f3f
typedef long long ll;
using namespace std;
const int MAXN = 1e5+5;
const int MOD = 1e9+7;
int r, c;
int pic[105][105];
int rec[105][105]; //记录每个点所能达到的最长路径
char dir[4][2] = {-1,0, 0,-1, 1,0, 0,1};//左上右下四个方向
int dfs(int x0, int y0)
{
if (rec[x0][y0] != -1)
return rec[x0][y0];//如果这个点已经被搜索过,那么直接拿其结果来用
rec[x0][y0] = 1;//如果没有搜索过,将值改为1,表示自身这一点
rep(i, 0, 3)
{
int x = x0 + dir[i][0];
int y = y0 + dir[i][1];
if (x>0 && y>0 && x<=r && y<=c && pic[x][y] < pic[x0][y0])
rec[x0][y0] = max(rec[x0][y0], dfs(x, y)+1);
//找出这一点向四个方向所能达到的最长路径,并记录下来
//因为能够到达下一个点,所以是dfs(x,y)+1
}
return rec[x0][y0]; //返回这一点的搜索结果
}
int main()
{
int ans = 0;
ms(rec, -1);
cin >> r >> c;
rep(i, 1, r)
rep(j, 1, c)
scanf("%d", &pic[i][j]);
rep(i, 1, r)
rep(j, 1, c)
ans = max(ans, dfs(i, j)); //记录最大值
cout << ans << endl;
return 0;
}