描述
trs喜欢滑雪。他来到了一个滑雪场,这个滑雪场是一个矩形,为了简便,我们用r行c列的矩阵来表示每块地形。为了得到更快的速度,滑行的路线必须向下倾斜。
例如样例中的那个矩形,可以从某个点滑向上下左右四个相邻的点之一。例如24-17-16-1,其实25-24-23…3-2-1更长,事实上这是最长的一条。
例如样例中的那个矩形,可以从某个点滑向上下左右四个相邻的点之一。例如24-17-16-1,其实25-24-23…3-2-1更长,事实上这是最长的一条。
输入格式
输入文件
第1行: 两个数字r,c(1<=r,c<=100),表示矩阵的行列。
第2..r+1行:每行c个数,表示这个矩阵。
第1行: 两个数字r,c(1<=r,c<=100),表示矩阵的行列。
第2..r+1行:每行c个数,表示这个矩阵。
输出格式
输出文件
仅一行: 输出1个整数,表示可以滑行的最大长度。
仅一行: 输出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;}