题目:D:滑雪
总时间限制: 1000ms 内存限制: 65536kB
描述
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。
输出
输出最长区域的长度。
样例输入
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
解题思路:L(i,j)表示从点(i,j)出发的最长滑行长度,一个点(i,j), 如果周围没有比它低的点,L(i,j) = 1,否则,递推公式: L(i,j) 等于(i,j)周围四个点中,比(i,j)低,且L值最大的那个点的L值,再加1。将所有点按高度从小到大排序,每个点的L值都初始化为1,从小到大遍历所有的点(用结构记录i,j和对应的高度,并按照其中的高度排序),经过一个点(i,j)时,用递推公式求L(i,j)。
#include<iostream>
#include<queue>
#include<algorithm>
using namespace std;
struct H//使用结构/类来给高度排序,同时可以记录该高度对应的i,j值
{
int i, j, value;
H(int _i, int _j, int _value):i(_i),j(_j),value(_value){}
bool operator<(const H & t)//重载大小定义
const//注意加上这个const,否则会报错!!!
{
return value > t.value;//每次优先级最高的是高度最小的
}
};
int main()
{
int r, c;
cin >> r >> c;
int a[r][c], l[r][c];
priority_queue<H> queue;
for(int i = 0; i < r; i++)
{
for(int j = 0; j < c; j++)
{
cin >> a[i][j];
queue.push(H(i, j, a[i][j]));
l[i][j] = 1;
}
}
while(!queue.empty())
{
int up, down, left, right;//(i,j)上下左右四个点高度值
int u_l, d_l, l_l, r_l;//(i,j)上下左右四个点l值
H h = queue.top();//处理当前还未处理过的高度最小的点
queue.pop();
//若不想处理边界情况,可以在当时创建数组时,外面加一圈边界,即a[r+2][c+2]
//存储它们的高度值都是大于10000的,则对结果不会有影响,可视为平常处理
//下面是没有加边界的处理方法,因此边界情况都要考虑到!!!
if(h.i == 0)
{
left = 10000;
l_l = 1;
right = a[h.i + 1][h.j];
r_l = l[h.i + 1][h.j];//(i+1, j)的l值
}
else if(h.i == r - 1)
{
right = 10000;
r_l = 1;
left = a[h.i - 1][h.j];
l_l = l[h.i - 1][h.j];//(i-1, j)的l值
}
else
{
left = a[h.i - 1][h.j];
l_l = l[h.i - 1][h.j];//(i-1, j)的l值
right = a[h.i + 1][h.j];
r_l = l[h.i + 1][h.j];//(i+1, j)的l值
}
if(h.j == 0)
{
up = 10000;
u_l = 1;
down = a[h.i][h.j + 1];
d_l = l[h.i][h.j + 1];//(i, j+1)的l值
}
else if(h.j == c - 1)
{
down = 10000;
d_l = 1;
up = a[h.i][h.j - 1];
u_l = l[h.i][h.j - 1];//(i, j-1)的l值
}
else
{
up = a[h.i][h.j - 1];
u_l = l[h.i][h.j - 1];//(i, j-1)的l值
down = a[h.i][h.j + 1];
d_l = l[h.i][h.j + 1];//(i, j+1)的l值
}
//(i,j)的上下左右四个点中高度比点(i,j)高度低的点,其l值是已知的,(而高度更高的点l值还未更新,只为1)
//但这里只用高度更低,l值已知的点,只能用它们的l值来更新(i,j)点的l值
//找到里面l值最大的,再加一即l[i][j],若没有比它低的点,则l[i][j]值不变
if(left < a[h.i][h.j])//也可写出h.value
l[h.i][h.j] = max(l[h.i][h.j], l_l + 1);
if(right < a[h.i][h.j])
l[h.i][h.j] = max(l[h.i][h.j], r_l + 1);
if(up < a[h.i][h.j])
l[h.i][h.j] = max(l[h.i][h.j], u_l + 1);
if(down < a[h.i][h.j])
l[h.i][h.j] = max(l[h.i][h.j], d_l + 1);
}
int max_l = 1;
for(int i = 0; i < r; i++)
for(int j = 0; j < c; j++)
max_l = max(max_l, l[i][j]);
cout << max_l <<endl;
system("pause");
return 0;
}