[TYVJ] P1004 滑雪
滑雪
背景 Background
成成第一次模拟赛 第三道
描述 Description
trs喜欢滑雪。他来到了一个滑雪场,这个滑雪场是一个矩形,为了简便,我们用r行c列的矩阵来表示每块地形。为了得到更快的速度,滑行的路线必须向下倾斜。
例如样例中的那个矩形,可以从某个点滑向上下左右四个相邻的点之一。例如24-17-16-1,其实25-24-23…3-2-1更长,事实上这是最长的一条。
例如样例中的那个矩形,可以从某个点滑向上下左右四个相邻的点之一。例如24-17-16-1,其实25-24-23…3-2-1更长,事实上这是最长的一条。
输入格式 InputFormat
输入文件
第1行: 两个数字r,c(1<=r,c<=100),表示矩阵的行列。
第2..r+1行:每行c个数,表示这个矩阵。
第1行: 两个数字r,c(1<=r,c<=100),表示矩阵的行列。
第2..r+1行:每行c个数,表示这个矩阵。
输出格式 OutputFormat
输出文件
仅一行: 输出1个整数,表示可以滑行的最大长度。
仅一行: 输出1个整数,表示可以滑行的最大长度。
样例输入 SampleInput [复制数据]
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
样例输出 SampleOutput [复制数据]
25
题解:
读完题第一个想法是记忆化搜索,据网上一些大牛介绍此方法可以AC。但思考了一段时间,发现可以转化为动态规划问题,这样会更简单,效率也很高。主要思路如下:
1.把二维矩阵拉成线性。用一个一维数组记录矩阵中所有数据a[i],另两个一维数组b[i],c[i]分别记录数据的X,Y坐标。
2.a[i]从小到大排序,b[i],c[i]跟随排序。
3.现在求最长路径就转化成了求该一维数组a[i]的最长上升子序列。这里要特别注意状态转移的条件。即a[i]、a[j]在矩阵中必须相邻,即abs(xi-xj)=1 && yi=yj或者 xi=xj &&abs(yi-yj)=1。
4.最后最长上升子序列的长度就是可以滑行的最大长度。
代码:
1 #include<stdio.h> 2 #include<math.h> 3 int 4 r,c1,i,j,n,num=0,maxx=1,a[11000],b[11000],c[11000],f[11000]; 5 int 6 max(int a,int b) 7 { 8 if (a>b) return(a); 9 else return(b); 10 } 11 12 void 13 qsort(int head,int tail) 14 { 15 int i,j,x,y,z; 16 i=head;j=tail; 17 x=a[head];y=b[head];z=c[head]; 18 while(i<j) 19 { 20 while((i<j)&&(a[j]>=x)) j--; 21 a[i]=a[j];b[i]=b[j];c[i]=c[j]; 22 while((i<j)&&(a[i]<=x)) i++; 23 a[j]=a[i];b[j]=b[i];c[j]=c[i]; 24 } 25 a[i]=x;b[i]=y;c[i]=z; 26 if (head<(i-1)) qsort(head,i-1); 27 if ((i+1)<tail) qsort(i+1,tail); 28 } 29 int 30 check(int x1,int y1,int x2, int y2) 31 { 32 int p,q; 33 p=abs(x1-x2); 34 q=abs(y1-y2); 35 if ((p==1)&&(y1==y2)) return 1; 36 if ((x1==x2)&&(q==1)) return 1; 37 return 0; 38 } 39 40 int 41 main(void) 42 { 43 int x; 44 scanf("%d%d\n",&r,&c1); 45 for(i=1;i<=r;i++) 46 for (j=1;j<=c1;j++) 47 { 48 scanf("%d",&x); 49 num++; 50 a[num]=x; 51 b[num]=i; 52 c[num]=j; 53 } 54 n=num; 55 56 57 qsort(1,n); 58 59 for (i=1;i<=n;i++) f[i]=1; 60 61 for (i=2;i<=n;i++) 62 for (j=1;j<i;j++) 63 { 64 if ((a[j]<a[i])&&(check(b[j],c[j],b[i],c[i])==1)) 65 f[i]=max(f[i],f[j]+1); 66 if (f[i]>maxx) maxx=f[i]; 67 } 68 printf("%d\n",maxx); 69 return 0; 70 } 71