滑雪

Description

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

16 17 18 19 6

15 24 25 20 7

14 23 22 21 8

13 12 11 10 9

一个人可以从某个点滑向上下左右相邻四个点之一,当且仅当高度减小。在上面的例子中,一条可滑行的滑坡为24-17-16-1。当然25-24-23-...-3-2-1更长。事实上,这是最长的一条。

Input

输入的第一行表示区域的行数R和列数C(1 <= R,C <= 100)。下面是R行,每行有C个整数,代表高度h,0<=h<=10000。

Output

输出最长区域的长度。

Sample Input

5 5
1 2 3 4 5
16 17 18 19 6
15 24 25 20 7
14 23 22 21 8
13 12 11 10 9

Sample Output

25


题解:这道题有多中做法。

1.首先既然是求最长路,可以用SPFA,因为SPFA更新的是当前能够更新的路径,但是每个点都会去遍历一次,然而,有点的点的最大值早就知道了。所以这会重复。

2.此外就是搜索了,如果其他点到该点的长度大于该点保存的最大值,更新。这样也回重算,因为我只需要四个点的最大值中最大的一个就行了,其他的没用。

3.计算每个点能够达到的最大值。


1.(超时)

#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>

using namespace std;

const int INF = 0x3fffffff;

struct Node
{
	int x;
	int y;
	Node(int a,int b)
	{
		x = a;
		y = b;
	}
};

bool visited[104][104];
int d[104][104];
int dir[4][2] = {{-1,0},{1,0},{0,-1},{0,1}};
int map[105][105];

int spfa(int,int,int,int);

int main()
{
	int n,m;
	while(scanf("%d%d",&n,&m) != EOF)
	{
		for(int i = 0;i < n;i++)
		{
			for(int j = 0;j < m;j++)
			{
				scanf("%d",&map[i][j]);
			} 
		}
		int res = 0;
		for(int i = 0;i < n;i++)
		{
			for(int j = 0;j < m;j++)
			{
				//if(map[i][j] == 1)
				{
					res = max(res,spfa(n,m,i,j));
				}
			}
		}
		
		printf("%d\n",res + 1);
	}
	
	return 0;
}

int spfa(int n,int m,int x,int y)
{
	memset(visited,false,sizeof(visited));
	memset(d,0,sizeof(d));
	queue<Node> q;
	q.push(Node(x,y));
	visited[x][y] = true;
	int t = 0;
	while(!q.empty())
	{
		Node p = q.front();
		q.pop();
		visited[p.x][p.y] = false;
//		t = max(t,d[p.x][p.y]);
		for(int i = 0;i < 4;i++)
		{
			x = p.x + dir[i][0];
			y = p.y + dir[i][1];
			if(x < 0 || x >= n || y < 0 || y >= m)
			{
				continue;
			}
			if(map[x][y] <= map[p.x][p.y])
			{
				continue;
			}
			if(d[x][y] < d[p.x][p.y] + 1)
			{
				d[x][y] = d[p.x][p.y] + 1;
				t = max(t,d[x][y]);
				if(!visited[x][y])
				{
					q.push(Node(x,y));
					visited[x][y] = true;
				}
			}
		}
	}
	
	return t;
}

2.(900ms)

#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>

using namespace std;

const int INF = 0x3fffffff;

struct Node
{
	int x;
	int y;
	Node(int a,int b)
	{
		x = a;
		y = b;
	}
};

bool visited[104][104];
int d[104][104];
int dir[4][2] = {{-1,0},{1,0},{0,-1},{0,1}};
int map[105][105];

void dfs(int x,int y,int n,int m)
{
	for(int i = 0;i < 4;i++)
	{
		int xx = x + dir[i][0];
		int yy = y + dir[i][1];
		if(xx < 0 || xx >= n || yy < 0 || yy >= m || map[xx][yy] <= map[x][y])
		{
			continue;
		}
		if(d[x][y] + 1 <= d[xx][yy]) //取到当前点最大的路径 
		{
			continue;
		}
		d[xx][yy] = d[x][y] + 1;
		dfs(xx,yy,n,m);
	}
}

int main()
{
	int n,m;
	while(scanf("%d%d",&n,&m) != EOF)
	{
		for(int i = 0;i < n;i++)
		{
			for(int j = 0;j < m;j++)
			{
				scanf("%d",&map[i][j]);
			} 
		}
		memset(d,0,sizeof(d));
		int res = 0;
		for(int i = 0;i < n;i++)
		{
			for(int j = 0;j < m;j++)
			{
				if(d[i][j] != 0)  //其实没必要判断,不过还是需要想到 
				{
					continue;
				}
				dfs(i,j,n,m);
			}
		}
		for(int i = 0;i < n;i++)
		{
			for(int j = 0;j  < m;j++)
			{
				if(res < d[i][j])
				{
					res = d[i][j];
				}
			}
		}
		printf("%d\n",res + 1);
	}
	
	return 0;
}

3.(最优)

#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>

using namespace std;

const int INF = 0x3fffffff;

struct Node
{
	int x;
	int y;
	Node(int a,int b)
	{
		x = a;
		y = b;
	}
};

bool visited[104][104];
int d[104][104];
int dir[4][2] = {{-1,0},{1,0},{0,-1},{0,1}};
int map[105][105];

int dfs(int x,int y,int n,int m)
{
	int t = 0;
	for(int i = 0;i < 4;i++)
	{
		int xx = x + dir[i][0];
		int yy = y + dir[i][1];
		if(xx < 0 || x >= n || yy < 0 || yy >= m || map[xx][yy] <= map[x][y])
		{
			continue;
		}
		if(d[xx][yy] > 1)
		    t = max(t,d[xx][yy]);
		else
		    t = max(t,dfs(xx,yy,n,m)); 
	}
	return d[x][y] = t + 1;   //该点最大值等于四个点最大值加1. 
}

int main()
{
	int n,m;
	while(scanf("%d%d",&n,&m) != EOF)
	{
		for(int i = 0;i < n;i++)
		{
			for(int j = 0;j < m;j++)
			{
				d[i][j] = 1;
				scanf("%d",&map[i][j]);
			} 
		}
		int res = 0;
		for(int i = 0;i < n;i++)
		{
			for(int j = 0;j < m;j++)
			{
				if(d[i][j] != 1)  //其实没必要判断,不过还是需要想到 
				{
					continue;
				}
				dfs(i,j,n,m);
			}
		}
		for(int i = 0;i < n;i++)
		{
			for(int j = 0;j  < m;j++)
			{
				if(res < d[i][j])
				{
					res = d[i][j];
				}
			}
		}
		printf("%d\n",res);
	}
	
	return 0;
}


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值