滑雪(动规例题)

题目大意:

指在一个r*c的矩阵里找一些连在一起的数的最长不下降子序列。


样例输入:

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

这道题很容易想到如果要求一个点的最长不下降子序列,只能从其上下左右四个方向得来——对于每个[i,j]点,只有可能从[i+x,j+y]得来,(x,y)=[(1,0),(-1,0),(0,1),(0,-1)]。然而要保证f[i+x,j+y]在f[i,j]点之前得出来,则需要对高度进行快排,并按高度的从矮到高依次来求值,最后输出r,c里面的最大f[i,j]。

f[i,j]:=min{f[i+x,j+y]+1}(a[i,j]>a[i+x,j+y])。


代码:

const
        dx:array[1..4] of Longint=(-1,0,1,0);
        dy:array[1..4] of Longint=(0,1,0,-1);
var
        r,c,i,j,k,ans,x,y,w:Longint;
        f,p:array[0..101,0..101] of Longint;
        a:Array[0..10000,1..3] of Longint;
procedure sort(l,r:Longint);
var
        i,j,mid,p:longint;
begin
        i:=l; j:=r;
        mid:=a[(l+r) div 2,1];
        while i<j do
        begin
                while a[i,1]<mid do inc(i);
                while a[j,1]>mid do dec(j);
                if i<=j then
                begin
                        a[0]:=a[i]; a[i]:=a[j]; a[j]:=a[0];
                        inc(i); dec(j);
                end;
        end;
        if l<j then sort(l,j);
        if i<r then sort(i,r);
end;

begin
        readln(r,c);
        fillchar(p,sizeof(p),5);
        for i:=1 to r do
                for j:=1 to c do
                begin
                        read(k);
                        w:=(i-1)*c+j;
                        p[i,j]:=k;
                        a[w,1]:=k; a[w,2]:=i; a[w,3]:=j;
                end;

        sort(1,r*c);

        for i:=1 to r*c do
                for k:=1 to 4 do
                begin
                        x:=a[i,2]; y:=a[i,3];
                        if (p[x,y]>p[x+dx[k],y+dy[k]]) and (f[x,y]<f[x+dx[k],y+dy[k]]+1) then
                                f[x,y]:=f[x+dx[k],y+dy[k]]+1
                end;
        for i:=1 to r do
                for j:=1 to c do
                        if f[i,j]>ans then ans:=f[i,j];
        writeln(ans+1);
end.


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值