[洛谷P1434] [SHOI2007]滑雪

题目链接:##

here we go

题外话:##

谁能想到这是一道咕了两年的\(AC\)呢……当年是在搜索还半懂不懂的时候遇到的这道题,感觉真是难得要命()所以一直拖着不做,后面就下意识地逃避了搜索相关的内容(慢慢变菜
(然后学树形\(dp\)数位\(dp\)的时候强行线性\(dp\)经常推不出被搞疯了)
咳咳,所以终于回来把这道题做了,也算是还债了吧。
有时候感觉自己真是像一头从小被拴在木桩上的象,习惯了之后就从来没想过去挑战一下尝试一下什么的,越来越惰怠,当然只能越来越弱了啊(

题目分析:##

首先这个题是一个很经典的记忆化搜索例题,经典到讲记忆化搜索十个教练有八个都会把这道题搬出来当例题。
所谓记忆化搜索,其本质仍然是递归。但由于递归时有许多重复的状态,所以会耗时巨大,而记忆化搜索以动态规划的方式记录了之前所计算过的状态,下次需要这个状态的时候不需要重新递归计算,而是可以直接拿来用,这样可以节省大量时间。

对于这个题,我们记录搜索到每一个点的最大路径长度,这样下次需要用这个点的时候就不需要再一次递归到头,而是直接调用即可。

顺便,我看题解里有不少判边界的(无限加高的,打判断的),其实可以反过来考虑,把滑雪看成爬坡,每一个\(dfs\)的点只能往高处走,这样递归的判断应该是

    if(Map[x][y]<Map[go_x][go_y]) {
        ...
    }

\(Map[]\)数组的初始值是\(0\),即边界的\(Map\)值都是\(0\),所以走到边界的时候这个判断语句的返回值永远是\(false\),直接规避了边界问题

对着每一个点\(dfs\)一遍(即把每个点当做终点搜一遍)取最大即可。

代码:##

#include <bits/stdc++.h>
#define N (100+5)
using namespace std;
inline int read() {
	int cnt = 0, f = 1; char c;
	c = getchar();
	while (!isdigit(c)) {
		if(c == '-') f = -f;
		c = getchar();
	}
	while (isdigit(c)) {
		cnt = cnt * 10 + c - '0';
		c = getchar();
	}
	return cnt * f;
}
int r, c;
int ans=-1;
int mapp[N][N], step[N][N];
const int fx[4] = {0, 1, 0, -1};
const int fy[4] = {1, 0, -1, 0};
int Dfs(int x, int y) {
	if(step[x][y]) return step[x][y];
	step[x][y] = 1;
	for (register int i = 0; i <= 3; i++) {
			int gx = x + fx[i]; int gy = y + fy[i];
			if(mapp[x][y] < mapp[gx][gy]) 
			step[x][y] = max(step[x][y], Dfs(gx, gy) + 1);
	}
	return step[x][y];
}
int main() {
	r = read();
	c = read();
	for (register int i = 1; i <= r; i++) 
		for (register int j = 1; j <= c; j++)
			mapp[i][j] = read();
			
	memset(step, 0, sizeof(step));
	for (register int i = 1; i <= r; i++) 
		for (register int j = 1; j <= c; j++)
			ans = max(ans, Dfs(i, j));
			
	printf("%d\n", ans);
	return 0;
}
posted @ 2019-03-16 10:30  kma_093  阅读(121)  评论(0编辑  收藏  举报