1088:滑雪
总时间限制: 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
来源
Don’t know
解题思路
解法一:“人人为我”式递推
L(i,j)表示从点(i,j)出发的最长滑行长度。
一个点(i,j),如果周围没有比它低的点,L(i,j)=1
将所有点按高度从小到大排序。每个点的L值都初始化为1
从小到大遍历所有的点。经过一个点(i,j)时,用递推公式求L(i,j)

- 先设每个区域的最长长度为 1;
- 对二维数组【此区域】进行从小到大排序
- 从找最低点开始逐个遍历,在周围找比它更低的点,更新长度
- 最后每个点都更新了他们的最长滑雪长度,找出最大值就可以啦
1.为什么排序?
因为A点的最长滑雪长度是 由 比A点低的B点的最长滑雪长度组成 ,相对低点B的最长滑雪长度是由比点B低的点C的最长滑雪长度组成。
所以从小到大排序后就从最小的点开始更新长度(递推就是一个从已知到未知推导的过程,针对本题,最小值的dp[][]=1已经知道,那从小到大搜索一定可以求出所有值,所以进行了排序操作)
2.为什么用结构体?
2.1因为在排序过程中,排序会改变它在二维数组原来的位置,故可以用结构体保存横纵坐标以及高度,方便接下来计算。
2.2 二维数组不可以用sort()直接排序,所以转化为结构体。
#include<iostream>
#include<algorithm>
using namespace std;
int maxLen[101][101];//存储每个点的最长滑雪长度,动态更新
int a[101][101];//每个点的高度
int xy[4][2]={
{
1,0},{
0,1},{
-1,0},{
0,-1}};
struct Node{
int x,y,num;//点的横坐标、纵坐标、高度
}node[10201];
bool cmp(struct Node n1,struct Node n2){
return n1.num<n2.num;
}
int max(int a,int b){
return a>b?a:b;
}
int main(){
int r,c,i,j,k=1,x,y,xx,yy,len,maxValue=0;
cin>>r>>c;
for(i=1;i<=r;i++){
for(j=1;j<=c;j++){
cin>>a[i][j];
node[k].x = i;
node[k].y = j;
node[k].num = a[i][j];
k++;
maxLen[i][j] = 1;//初始化每个点的长度为1
}
}
sort(node+1,node+r*c+1,cmp);//从小到大排序
for(i=1;i<=r*c;i++){
x = node[i].x;
y = node[i].y;
for(j=0;j<4;j++){
//对该点的周围进行遍历比较
xx = x+xy[j][0];
yy = y+xy[j][1];
if(xx>=1&&xx<=r&&yy>=1&&yy<=c&&a[x][y]>a[xx][yy]){
//xx<=r写成了xx<=c!!!
maxLen[x][y] = max(maxLen[x][y],maxLen[xx][yy]+1);
}
}
maxValue = max(maxLen[x][y],maxValue);
}
cout<<maxValue<<endl;
return 0;
}
解法二:“我为人人”式递推
L(i,j)表示从点(i,j)出发的最长滑行长度。
一个点(i,j),如果周围没有比它低的点,L(i,j)= 1
将所有点按高度从小到大排序。每个点的L值都初始化为1
从小到大遍历所有的点。经过一个点(i,j)时,要更新他周围的,比它高的点的L值。例如:
if H(i+1,j)> H(i.j) //H代表高度
L(i+1,j) = max(L(i+1,j),L(i,j)+1)
这代码运行结果是对的,但是提交上去却是错的,不知道哪位大佬能看出哪里错!!
#include<iostream>
#include<algorithm>
using namespace std;
int maxLen[101][101];//存储每个点的最长滑雪长度,动态更新
int a[101][101];//每个点的高度
int xy[4][2]={
{
1,0},{
0,1},{
-1,0},{
0,-1}};
struct Node{
int x,y,num;//点的横坐标、纵坐标、高度
}node[10201];
bool cmp(struct Node n1,struct Node n2){
return n1.num<n2.num;
}
int max(int a,int b){
return a>b?a:b;
}
int main(){
int r,c,i,j,k=1,x,y,xx,yy,len,maxValue=0;
cin>>r>>c;
for(i=1;i<=r;i++){
for(j=1;j<=c;j++){
cin>>a[i][j];
node[k].x = i;
node[k].y = j;
node[k].num = a[i][j];
k++;
maxLen[i][j] = 1;//初始化每个点的长度为1
}
}
sort(node+1,node+r*c+1,cmp);//从小到大排序
for(i=1;i<=r*c;i++){
x = node[i].x;
y = node[i].y;
for(j=0;j<4;j++){
xx = x+xy[j][0];
yy = y+xy[j][1];
//在解法一的基础上,下面这段代码做了改动
if(xx>=1&&xx<=r&&yy>=1&&yy<=c&&a[x][y]<a[xx][yy]){
maxLen[xx][yy] = max(maxLen[x][y]+1,maxLen[xx][yy]);
maxValue = max(maxLen[xx][yy],maxValue);
}
}
}
cout<<maxValue<<endl;
return 0;
}