「SHOI2002」滑雪-记忆化搜索

Michael喜欢滑雪。这并不奇怪,因为滑雪的确很刺激。可是为了获得速度,滑的区域必须向下倾斜,而且当你滑到坡底,你不得不再次走上坡或者等待升降机来载你。Michael想知道在一个区域中最长的滑坡。区域由一个二维数组给出。数组的每个数字代表点的高度。

然而, 当且仅当高度减小时,一个人可以从某个点滑向上下左右相邻四个点之一。

Links

Luogu P1434

Solution

看到这道题第一眼有可能会想到线性DP,这道题用DP确实也能做,但它其实是一个标准的记忆化搜索,直接枚举从每一个点作为起点扩展时滑雪路径的长度,然后始终取最大值即可

Code

#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
const int maxn=110;
int dx[]={0,0,1,-1},dy[]={1,-1,0,0};//在x,y坐标上的四个方向
int a[maxn][maxn],book[maxn][maxn];
int r,c;
void read(int &amp;x){ //输入优化
	x=0;char c=getchar();
	while(c<'0' || c>'9')c=getchar();
	while(c>='0' &amp;&amp; c<='9'){
		x=x*10+c-'0';
		c=getchar();
	} 
}
inline int dfs(int x,int y){ //以(x,y)为起点开始扩展
	int tmp=1;
	if(book[x][y]) return book[x][y];//记忆化部分,如果已经搜过了,直接返回搜出来的值
	for(int i=0;i<4;i++){
		if(x+dx[i]<1 || x+dx[i]>r || y+dy[i]<1 || y+dy[i]>c) continue;//边界
		if(a[x+dx[i]][y+dy[i]]<a[x][y]){
			tmp=max(book[x][y],dfs(x+dx[i],y+dy[i])+1);
			book[x][y]=tmp;
		}
	}
	return tmp;
}
int main(){
	int ans=0;
	scanf("%d%d",&amp;r,&amp;c);
	for(int i=1;i<=r;i++){
		for(int j=1;j<=c;j++){
			read(a[i][j]);
		}
	}
	for(int i=1;i<=r;i++){
		for(int j=1;j<=c;j++){
			ans=max(dfs(i,j),ans);//以每个点为起点扩展,最后ans为最长的那条路径
		}
	}
	printf("%d\n",ans);
	return 0;
}

发表评论

电子邮件地址不会被公开。 必填项已用*标注