您的位置:首页 > 其它

[TYVJ] P1004 滑雪

2014-03-10 22:39 267 查看
[b]滑雪[/b]

背景 Background
成成第一次模拟赛 第三道

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

输入格式 InputFormat
输入文件

第1行: 两个数字r,c(1<=r,c<=100),表示矩阵的行列。
第2..r+1行:每行c个数,表示这个矩阵。

输出格式 OutputFormat
输出文件

仅一行: 输出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

题解:

[b] 读完题第一个想法是记忆化搜索,据网上一些大牛介绍此方法可以AC。但思考了一段时间,发现可以转化为动态规划问题,这样会更简单,效率也很高。主要思路如下:[/b]

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.最后最长上升子序列的长度就是可以滑行的最大长度。

代码:

#include<stdio.h>
#include<math.h>
int
r,c1,i,j,n,num=0,maxx=1,a[11000],b[11000],c[11000],f[11000];
int
max(int a,int b)
{
if (a>b) return(a);
else return(b);
}

void
qsort(int head,int tail)
{
int i,j,x,y,z;
i=head;j=tail;
x=a[head];y=b[head];z=c[head];
while(i<j)
{
while((i<j)&&(a[j]>=x)) j--;
a[i]=a[j];b[i]=b[j];c[i]=c[j];
while((i<j)&&(a[i]<=x)) i++;
a[j]=a[i];b[j]=b[i];c[j]=c[i];
}
a[i]=x;b[i]=y;c[i]=z;
if (head<(i-1)) qsort(head,i-1);
if ((i+1)<tail) qsort(i+1,tail);
}
int
check(int x1,int y1,int x2, int y2)
{
int p,q;
p=abs(x1-x2);
q=abs(y1-y2);
if ((p==1)&&(y1==y2)) return 1;
if ((x1==x2)&&(q==1))  return 1;
return 0;
}

int
main(void)
{
int x;
scanf("%d%d\n",&r,&c1);
for(i=1;i<=r;i++)
for (j=1;j<=c1;j++)
{
scanf("%d",&x);
num++;
a[num]=x;
b[num]=i;
c[num]=j;
}
n=num;

qsort(1,n);

for (i=1;i<=n;i++)  f[i]=1;

for (i=2;i<=n;i++)
for (j=1;j<i;j++)
{
if ((a[j]<a[i])&&(check(b[j],c[j],b[i],c[i])==1))
f[i]=max(f[i],f[j]+1);
if (f[i]>maxx) maxx=f[i];
}
printf("%d\n",maxx);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: