滑雪
总时间限制: 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
[Solution]
用结构体存下每个点高度和横纵坐标,然后按高度由大到小排序,N2判断合法且可以到达的点,然后转成序列DP即可。
AC代码:
1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 using namespace std; 5 int N,M,cnt,ans=-1; 6 int dp[20010]; 7 struct pack {int x,y,ht;} data[20010]; 8 int cmp(const pack &a,const pack &b){ 9 return a.ht>b.ht; 10 } 11 int jdg(int x,int y){ 12 if(data[y].x==data[x].x+1&&data[y].y==data[x].y) return 1; 13 if(data[y].x==data[x].x&&data[y].y==data[x].y+1) return 1; 14 if(data[y].x==data[x].x-1&&data[y].y==data[x].y) return 1; 15 if(data[y].x==data[x].x&&data[y].y==data[x].y-1) return 1; 16 return 0; 17 } 18 int main(){ 19 scanf("%d%d",&N,&M); 20 for(int i=1;i<=N;++i) 21 for(int j=1;j<=M;++j){ 22 scanf("%d",&data[++cnt].ht); 23 data[cnt].x=i; data[cnt].y=j; 24 } 25 sort(data+1,data+1+cnt,cmp); 26 for(int i=1;i<cnt;++i) 27 for(int j=i+1;j<=cnt;++j) 28 if(jdg(i,j)&&data[j].ht<data[i].ht) dp[j]=max(dp[j],dp[i]+1); 29 for(int i=1;i<=cnt;++i) 30 if(dp[i]>ans) ans=dp[i]; 31 printf("%d",ans+1); 32 return 0; 33 }