NYACM_010
题目:skiing
链接:http://acm.nyist.net/JudgeOnline/problem.php?pid=10
描述:
描述
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更长。事实上,这是最长的一条。
输入
第一行表示有几组测试数据,输入的第二行表示区域的行数R和列数C(1 <= R,C <= 100)。下面是R行,每行有C个整数,代表高度h,0<=h<=10000。
后面是下一组数据;
输出
输出最长区域的长度。
样例输入
1
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
样例输出
25
分析:
刚才CSDN博客无法使用MarkDown编辑器,所以分析都直接写在了code里面。其实除去背景描述,就是一个最大联通分枝问题,直接用一个二维数组存储原始数据,另一个等大数组存储该点能达到当最大长度,任意一点能够达到当长度为:1,如果四周都不可达;可达点中最大值+1。
AC Code:
/*
2017年12月18日21:51:39
CSDN出了问题,不好写博客,先把问题解了再说
skiing
时间限制:3000 ms | 内存限制:65535 KB
难度:5
描述
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更长。事实上,这是最长的一条。
输入
第一行表示有几组测试数据,输入的第二行表示区域的行数R和列数C(1 <= R,C <= 100)。下面是R行,每行有C个整数,代表高度h,0<=h<=10000。
后面是下一组数据;
输出
输出最长区域的长度。
样例输入
1
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
样例输出
25
抛却背景,其实就是找最长通路,图的遍历问题
采用二位数组保存数据,从第一个点开始,通过深度优先找到最大长度。
*/
#include <iostream>
using namespace std;
int Data[100][100] = { 0 };
int MaxLength[100][100] = { 0 }; //用来记录改点能达到的最大长度,可以方便后面计算
//判断两点是否可达
int IsReachable(int x0, int y0,int x,int y,int maxx,int maxy )
{
int ret = 1;
//不可达有两种情况,数字较小,或者越出边界
if (x < 0 | y < 0 | x>=maxx | y>=maxy)
{
return 0;
}
if (Data[x0][y0] <= Data[x][y])
{
return 0;
}
return ret;
}
//用来计算某一点的最大可达长度
int GetMaxLength(int x,int y,int maxx,int maxy)
{
int ret = 0;
if (MaxLength[x][y] != 0)
{
//这个点已经算过最大可达长度
return MaxLength[x][y];
}
else
{
//还没求出该点的值
//点的位置不同,可能的到达点也不同,最多有四个
int tmp_max = 1;
if (IsReachable(x, y, x - 1, y, maxx, maxy) == 1)
{
int tmp = GetMaxLength(x - 1, y, maxx, maxy)+1;
if (tmp_max < tmp)
{
tmp_max = tmp;
}
}
if (IsReachable(x, y, x, y-1, maxx, maxy) == 1)
{
int tmp = GetMaxLength(x, y-1, maxx, maxy)+1;
if (tmp_max < tmp)
{
tmp_max = tmp;
}
}
if (IsReachable(x, y, x + 1, y, maxx, maxy) == 1)
{
int tmp = GetMaxLength(x + 1, y, maxx, maxy)+1;
if (tmp_max < tmp)
{
tmp_max = tmp;
}
}
if (IsReachable(x, y, x, y+1, maxx, maxy) == 1)
{
int tmp = GetMaxLength(x, y+1, maxx, maxy)+1;
if (tmp_max < tmp)
{
tmp_max = tmp;
}
}
MaxLength[x][y] = tmp_max;
return tmp_max;
}
return ret;
}
int main()
{
int N;
cin >> N;
while (N--)
{
int R, C;
cin >> R >> C;
for (int i = 0; i < R; i++)
{
for (int j = 0; j < C; j++)
{
int tmp;
cin >> tmp;
Data[i][j] = tmp;;
}
}
//现在有了所有数据,进行处理,从每一个点出发,看能达到的最大长度是多少
for (int i = 0; i < R; i++)
{
for (int j = 0; j < C; j++)
{
//获取该点能达到的最大长度,做法为:
//该点能达到的最大程度为四个方向中能够到达中能达到的最大长度中的最大值+1,
//比如点[0][0],最多只有两个可达点,如果这两个点都可达,两者当中最大值+1,
//如果都不可达,最大长度1
//如果下一可达点值0,表示还没进行计算,重复上面动作,如果标记值非0,直接得到可达最大长度
GetMaxLength(i, j, R, C);
}
}
//获取最大值
int answer = 0;
for (int i = 0; i < R; i++)
{
for (int j = 0; j < C; j++)
{
if (answer < MaxLength[i][j])
{
answer = MaxLength[i][j];
}
}
}
cout << answer << endl;
//完成一次的处理,恢复数据原状
for (int i = 0; i < R; i++)
{
for (int j = 0; j < C; j++)
{
Data[i][j]=0;
}
}
for (int i = 0; i < R; i++)
{
for (int j = 0; j < C; j++)
{
MaxLength[i][j] = 0;
}
}
}
return 0;
}
其他
相对比较简单,112/312 AC,下面有人44/312,感觉主要是递归有点浪费时间,不过目前主要目标不是追求这个,暂且这样了,前面线段树问题导致耽误了好久,本来计划一天一个的,如果想要赶上进度,趁着题目简单尽可能多做几个了。虽然这个相对没有什么难度,还是第三次才AC, 主要是边界没设好,下标不能达到长度,粗心所致。