tyvj p1004 滑雪

描述

    trs喜欢滑雪。他来到了一个滑雪场,这个滑雪场是一个矩形,为了简便,我们用r行c列的矩阵来表示每块地形。为了得到更快的速度,滑行的路线必须向下倾斜。
    例如样例中的那个矩形,可以从某个点滑向上下左右四个相邻的点之一。例如24-17-16-1,其实25-24-23…3-2-1更长,事实上这是最长的一条。

输入格式

输入文件

第1行: 两个数字r,c(1<=r,c<=100),表示矩阵的行列。
第2..r+1行:每行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

输出

25



       根据题意可以轻易想出搜索。但是没有优化的搜索时间复杂度高达指数级,显然不可取。这里使用动态规划的方法。

       首先假设题目是一维的,那么问题就很简单了——最长连续下降子序列,可以在O(n^2)的时间内解决,对于题目的数据范围已经可以接受了。现在只是增加了一个维度,题目本质并没有什么变化。

       首先进行降维处理——将二维矩阵变位一维数组,当然需要记录每个点的坐标。然后按高度从小到大进行排序,然后求最长严格上升子序列(反过来从大到小排序,求严格下降子序列也可以)。如何求最长上升子序列不详细说明。当然,这样得到的答案只是最长,但是放到原来的数据中他们不一定是连续的,所以只需要在判断过程中加一个限制条件——两点挨着就可以。



#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
#define max(a,b) ((a>b)? a:b)
using namespace std;
long n,m;
struct shuxing
{long x,y;
 long h;} s[10010];
long f[10010];

bool cmp(shuxing a,shuxing b)
{return a.h<b.h;}

bool xianglin(long a,long b)
{if(abs(s[a].x-s[b].x)==1 && s[a].y==s[b].y) return true;
 if(abs(s[a].y-s[b].y)==1 && s[a].x==s[b].x) return true;
 return false;}

int main()
{cin>>n>>m;
 long a=0;
 for(long i=1;i<=n;i++)
  for(long j=1;j<=m;j++){s[++a].x=i;
                         s[a].y=j;
						 cin>>s[a].h;}
 sort(s+1,s+1+a,cmp);
 //for(long i=1;i<=a;)
 /*DP*/
 for(long i=1;i<=a;i++) f[i]=1;
 for(long i=a-1;i>0;i--)  
 {for(long j=i+1;j<=a;j++)  
  {if((s[j].h>s[i].h)&&(f[i]<f[j]+1)&&xianglin(i,j)) f[i]=f[j]+1;}}
 /*DPend*/
 long ff=0;
 for(long i=1;i<=a;i++) ff=max(ff,f[i]);
 cout<<ff<<endl;
 return 0;}

posted on 2015-09-21 23:33  lcyzgdy  阅读(306)  评论(0编辑  收藏  举报

导航