题解 UVA10285 【最长的滑雪路径 Longest Run on a Snowboard】

posted on 2021-03-01 18:05:25 | under 题解 | source

此题正解是记忆化搜索,我们先考虑暴力 dfs。

显然,我们可以在 \(\operatorname{dfs}\) 中传 \(3\) 个参数:\(x,y,cnt\),分别表示当前的位置和滑雪路径的长度。每次更新答案,并往另外 \(4\) 个点继续搜。

void dfs(int x,int y,int cnt){
	ans=Max(ans,cnt);
	for(int i=1;i<=4;i++){
		int tmpx=x+dx[i],tmpy=y+dy[i];
		if(tmpx<1||n<tmpx||tmpy<1||m<tmpy) continue;
		if(a[tmpx][tmpy]>=a[x][y]) continue;
      	//我们可以不标记走过的点,因为你不可能滑下来又滑上去
		dfs(tmpx,tmpy,cnt+1);
	}
}

这种方法是正确的,但时间复杂度达到了 \(O(4^{nm})\),会 TLE,考虑优化。

不难发现,从一个点出发的最长滑雪路径的长度是一定的,搜过一次,下次再搜,会浪费很多时间。我们可以把这个最长滑雪路径的长度用一个数组 \(f\) 存起来,使用 \(f_{x,y}\) 表示 \((x,y)\) 从这个点出发的最长滑雪路径,如果搜过了,\(f_{x,y}\) 会有一个值,这时候就不用继续搜索下去了,直接返回 \(f_{x,y}\)

为了方便,我们可以让 \(f\) 数组初始化为 \(-1\),判断 \(f_{x,y}\) 有没有值时可以写成if(~f[x][y]),这样能避免"从这个点出发的最长滑雪路径的长度为 \(0\) 而继续搜"的情况。

这就是记忆化搜索的思想,经过记忆化,时间复杂度从 \(O(4^{nm})\) 优化成了 \(O(nm)\)

下面是代码:

#include <cstdio>
#include <cstring>
using namespace std;
template<class T>
T Max(T _,T __){return _<__?__:_;}
template<class T>
T Min(T _,T __){return _>__?__:_;}
const int dx[5]={0,-1,0,0,1},
		  dy[5]={0,0,-1,1,0};//四个方向打表
int n,m,a[110][110],ans;
int f[110][110];
int dfs(int x,int y,int cnt){//注意记忆化的 dfs 有返回值
	if(~f[x][y]) return f[x][y];//记忆化
	int maxcnt=0;//记录最长滑雪路径的长度
	for(int i=1;i<=4;i++){
		int tmpx=x+dx[i],tmpy=y+dy[i];
		if(tmpx<1||n<tmpx||tmpy<1||m<tmpy) continue;
		if(a[tmpx][tmpy]>=a[x][y]) continue;
		maxcnt=Max(maxcnt,dfs(tmpx,tmpy,cnt+1)+1);
     	//最长滑雪路径包括这个点本身,要 +1
	}
	return f[x][y]=maxcnt;//赋值语句有返回值
}
int mian(){
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;i++)
		for(int j=1;j<=m;j++)
			scanf("%d",&a[i][j]);
	ans=0;
	for(int i=1;i<=n;i++)
		for(int j=1;j<=m;j++)
			ans=Max(ans,dfs(i,j,1));
  	//注意,最长滑雪路径不一定从最高的点开始,要每个点搜一次
	return 0;
}
char ipt[100010];
int main(int T){//其实可以偷 main 的参数的
	for(scanf("%d",&T)/*偷过来用*/;T--;puts("")){
		memset(a,0,sizeof a);
		memset(f,-1,sizeof f);//以上为多测日常操作
      	scanf("%s",ipt);
		mian();
		printf("%s: %d",ipt,ans+1);//因为一些玄学问题 ans 要 +1
	}
	return 0;
}

另外,此题与P1434 [SHOI2002]滑雪是双倍经验。

posted @ 2022-11-10 09:20  caijianhong  阅读(40)  评论(0编辑  收藏  举报