[OpenJudge90][序列DP+乱搞]滑雪

滑雪

总时间限制: 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 }

 

posted @ 2016-10-26 21:09  Reddest  阅读(428)  评论(0编辑  收藏  举报