Description
Michael喜欢滑雪百这并不奇怪, 因为滑雪的确很刺激。可是为了获得速度,滑的区域必须向下倾斜,而且当你滑到坡底,你不得不再次走上坡或者等待升降机来载你。Michael想知道载一个区域中最长底滑坡。区域由一个二维数组给出。数组的每个数字代表点的高度。下面是一个例子
一个人可以从某个点滑向上下左右相邻四个点之一,当且仅当高度减小。在上面的例子中,一条可滑行的滑坡为24-17-16-1。当然25-24-23-...-3-2-1更长。事实上,这是最长的一条。
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;
}