题目描述
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-11(从 24 开始,在 1 结束)。当然 25-24-23-…-3-2-1 更长。事实上,这是最长的一条。
输入格式
输入的第一行为表示区域的二维数组的行数 R 和列数 C。下面是 R 行,每行有C 个数,代表高度(两个数字之间用 1 个空格间隔)。
输出格式
输出区域中最长滑坡的长度。
输入输出样例
输入 #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
输出 #1
25
分析&思路:
这道题是一个DP,从高度较低的点向高度较高的点推,再找到最大的点,输出它的值。但是动态规划必须是有序的,所以在这里我们要将这个二维的数组展开成一维的,进行排序后它就有序了。
CODE:
#include<iostream>
#include<algorithm>
#include<cstdio>
using namespace std;
int n,m,g[10010],maxx;
const int dx[5]={0,-1,1,0,0};
const int dy[5]={0,0,0,1,-1};
struct node{
int value;//值
int x;//横坐标
int y;//纵坐标
}f[10010];
bool cmp(node x,node y)
{
return x.value<y.value;
}
int main()
{
cin>>n>>m;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
{
scanf("%d",&f[(i-1)*m+j].value);
f[(i-1)*m+j].x=i;f[(i-1)*m+j].y=j;//预处理
}
sort(f+1,f+n*m+1,cmp);//排序
//以下为DP部分
for(int i=1;i<=n*m;i++)//枚举全部
for(int j=i-1;j>0;j--)//从高到低
for(int k=1;k<=4;k++)//四个方向
if(f[i].x==f[j].x+dx[k]&&f[i].y==f[j].y+dy[k]&&f[i].value>f[j].value)//判断是否合法
{
g[i]=max(g[j]+1,g[i]);//动态转移
if(g[i]>maxx)//取最大值
maxx=g[i];
}
cout<<maxx+1;//因为本身也算一个节点
}