zoukankan      html  css  js  c++  java
  • 解北大OJ1088滑雪问题的记录


    问题:

    Time Limit:1000MS

     

    Memory Limit:65536K

    Total Submissions:67600

     

    Accepted:24862

    Description

    Michael 喜欢滑雪百这并不奇怪, 因为滑雪的确很刺激。可是为了获得速度,滑的区域必须向下倾斜,而且当你滑到坡底,你不得不再次走上坡或者等待升降机来载你。Michael想知道载一个 区域中最长底滑坡。区域由一个二维数组给出。数组的每个数字代表点的高度。下面是一个例子

     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


    一个人可以从某个点滑向上下左右相邻四个点之一,当且仅当高度减小。在上面的例子中,一条可滑行的滑坡为24-17-16-1。当然25-24-23-...-3-2-1更长。事实上,这是最长的一条。

    Input

    输入的第一行表示区域的行数R和列数C(1 <= R,C <= 100)。下面是R行,每行有C个整数,代表高度h,0<=h<=10000。

    Output

    输出最长区域的长度。

    Sample Input

    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

    Sample Output

    25

    Source

    SHTSC 2002



    示意图如下:


                                                                                  图一

    思路一:从每个高度开始,不断搜索路径,直到局部极小处。然后找出最大值。但这种方式会导致搜索重复的路径。

    思路二:可用动态规划,剔除思路一中需要重复搜索的路径,大大减少搜索次数。

    {动态规划的经典的例子为找两城市之间的最短路径。


                                                                     图二

        从A到F的所有路径穿过图中串着E和D的竖线,假设E在最短路径上,那么从A到E的路径也应该选最短的,否则将有另外一条较短的从A到E的路径A’—>E’->F更短;往前推,从A到E的路径穿过B和C,假设B在最短路径上,那么从A到B的路径也应该选最短的,从A到E的一条可能最短路径为从A到B的最短路径+B和E之间的距离。C和D点同理。

        因此,从A点出发,先得出A->B和A->C的最短路径,然后再得出A->E和A->D的最短路径,最后得出A->F的最短路径。

    如图,在得到A->B和A->C的最短路径后,求A->E和A->D的最短路径时,减少了A->B和A->C的两次搜索。在得到A->E的最短路径时,剔除了A->B->E,在得到A->D的最短路径时,剔除了A->C->D,这样在得到A->F的最短路径时,又减少了两次搜索。而且减少的搜索次数是同节点个数N成正比的。通过记录逐段的搜索结果,达到减少搜索次数的目的。}

         因此此题可以按照高度值,从高到低,逐次求得到达每个点的最长滑坡,最后再求出最长的滑坡。如图一,从A点到E点的最长滑坡为A->F->E.A点能影响到达F点和E点的最长滑坡,而F点也能影响到达E点的最长滑坡,因此当高度从A点变为F点时,到达E点的最长滑坡已经能知道应该从A->E改为A->F->E.假设从E点到B点还有其他路径的话,那么从A到E点的最长滑坡的确定就能减少搜索次数。时间复杂度为O(n)。

    例如:

    input

     2 3

     2 5 3

     6 1 2

    Output

    4

    求解过程为:

    1.1、2、2、3、5、6各点初始化滑坡长度值为1;

    2.6影响上面的2和右面的1,使他们的长度值分别加1变为2;

    3.5影响右面的3,使其长度值加1变为2;

    4.3影响下面的2,使其长度值加2变为3;

    5.6上面的2处于局部极小(谷底)不影响;

    6.3下面的2影响左面的1,使其长度值加3变为4;

    7.1处于局部极小(谷底)不影响。

    得到最大值为4.






    附录:

    这是我在北大OJ里提交的AC源代码,但是在Time和Memory方面还有待提高。其中在判断某点四个方向上的情况时,并未有效减少对于不可能的方向的情况的判断,而且代码看起来冗余。用一维数组表示的二维数组,动态分配的内存。说来也比较巧,当我做完后,在网上搜索了下,发现有些人的代码跟我的几乎差不多。

    Source Code

    Problem:1088

     

    User:lilin_xuebao

    Memory:508K

     

    Time:32MS

    Language:G++

     

    Result:Accepted

    · Source Code

    #include<stdio.h>

    #include<stdlib.h>

     struct H

     {

        int height;

        int length;

     };

        

    int cmp(const void *key,const void *data)

    {

    if((*(struct H**)key)->height < (*(struct H**)data)->height)

        return 1;

        return -1;

    }

    int main()

    {

        int rows=0,columns=0;

        struct H * array=NULL;

        struct H **temp=NULL;

        int total;

        scanf("%d%d",&rows,&columns);

        total=rows*columns;

        array=(struct H*)malloc(sizeof(struct H)*total);

        temp=(struct H**)malloc(sizeof(struct H *)*total);

        if(array == NULL||temp==NULL)return 0;

        

        int i;

        for(i=0;i<total;i++)

        {

            scanf("%d",&(array[i].height));

            array[i].length=1;

            temp[i]=&array[i];

        }

        

        qsort(temp,total,sizeof(struct H*),cmp);

        

        int up,down,left,right;

        int tempindex;

        int max=-1;

        for(i=0;i<total;i++)

        {

            tempindex=temp[i]-array;

            up=tempindex-columns;

            down=tempindex+columns;

            left=tempindex-1;

            right=tempindex+1;

            

            if(up>=0&&array[tempindex].height>array[up].height)

            {

              if(array[tempindex].length+1>array[up].length)

              {

                  array[up].length=array[tempindex].length+1;

              }

            }

            if(down<total&&array[tempindex].height>array[down].height)

            {

              if(array[tempindex].length+1>array[down].length)

              {

                  array[down].length=array[tempindex].length+1;

              }

            }

            if((left+1)%columns!=0&&array[tempindex].height>array[left].height)

            {

              if(array[tempindex].length+1>array[left].length)

              {

                  array[left].length=array[tempindex].length+1;

              }

            }

            if(right%columns!=0&&array[tempindex].height>array[right].height)

            {

              if(array[tempindex].length+1>array[right].length)

              {

                  array[right].length=array[tempindex].length+1;

              }

            }

            if(array[tempindex].length>max)max=array[tempindex].length; 

        }

        

        printf("%d",max);

        

        free(array);

        free(temp);

            

        return 0;    

    }


  • 相关阅读:
    upc组队赛3 T-net【贪心】
    upc组队赛5 Assembly Required【思维】
    upc组队赛5 Bulbs
    upc组队赛5 Ingenious Lottery Tickets【排序】
    upc组队赛5 Hunter’s Apprentice 【判断多边形边界曲线顺逆时针】
    upc组队赛5 Ground Defense【枚举】
    upc组队赛4 Go Latin
    upc组队赛4 TV Show Game 【2-SAT】
    POJ 3250 Bad Hair Day【单调栈入门】
    016.NET5_MVC_视图组件扩展定制
  • 原文地址:https://www.cnblogs.com/riskyer/p/3225814.html
Copyright © 2011-2022 走看看