• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            The Fourth Dimension Space

            枯葉北風寒,忽然年以殘,念往昔,語默心酸。二十光陰無一物,韶光賤,寐難安; 不畏形影單,道途阻且慢,哪曲折,如渡飛湍。斬浪劈波酬壯志,同把酒,共言歡! -如夢令

            最長上升子序列LIS(Longest Increasing Subsequence)

            最長上升子序列問題是各類信息學競賽中的常見題型,也常常用來做介紹動態規劃算法的引例,筆者接下來將會對POJ上出現過的這類題目做一個總結,并介紹解決LIS問題的兩個常用算法(n^2)和(nlogn).
            問題描述:給出一個序列a1,a2,a3,a4,a5,a6,a7....an,求它的一個子序列(設為s1,s2,...sn),使得這個子序列滿足這樣的性質,s1<s2<s3<...<sn并且這個子序列的長度最長。輸出這個最長的長度。(為了簡化該類問題,我們將諸如最長下降子序列及最長不上升子序列等問題都看成同一個問題,其實仔細思考就會發現,這其實只是<符號定義上的問題,并不影響問題的實質)
            例如有一個序列:1  7  3  5  9  4  8,它的最長上升子序列就是 1 3 4 8 長度為4.

            算法1(n^2):我們依次遍歷整個序列,每一次求出從第一個數到當前這個數的最長上升子序列,直至遍歷到最后一個數字為止,然后再取dp數組里最大的那個即為整個序列的最長上升子序列。我們用dp[i]來存放序列1-i的最長上升子序列的長度,那么dp[i]=max(dp[j])+1,(j∈[1, i-1]); 顯然dp[1]=1,我們從i=2開始遍歷后面的元素即可。
            下面是模板:

            //最長上升子序列(n^2)模板
            //入口參數:1.數組名稱 2.數組長度(注意從1號位置開始)
            template<class T>
            int LIS(T a[],int n)
            {
                
            int i,j;
                
            int ans=1;
                
            int m=0;
                
            int *dp=new int[n+1];
                dp[
            1]=1;
                
            for(i=2;i<=n;i++)
                
            {
                    m
            =0;
                    
            for(j=1;j<i;j++)
                    
            {
                        
            if(dp[j]>m&&a[j]<a[i])
                            m
            =dp[j];
                    }

                    dp[i]
            =m+1;
                    
            if(dp[i]>ans)
                        ans
            =dp[i];
                }

                
            return ans;
            }


            算法2(nlogn):維護一個一維數組c,并且這個數組是動態擴展的,初始大小為1,c[i]表示最長上升子序列長度是i的所有子串中末尾最小的那個數,根據這個數字,我們可以比較知道,只要當前考察的這個數比c[i]大,那么當前這個數一定能通過c[i]構成一個長度為i+1的上升子序列。當然我們希望在C數組中找一個盡量靠后的數字,這樣我們得到的上升子串的長度最長,查找的時候使用二分搜索,這樣時間復雜度便下降了。
            模板如下:

            //最長上升子序列nlogn模板
            //入口參數:數組名+數組長度,類型不限,結構體類型可以通過重載運算符實現
            //數組下標從1號開始。
            /////////////////////////BEGIN_TEMPLATE_BY_ABILITYTAO_ACM////////////////////////////
            template<class T>
            int bsearch(T c[],int n,T a) 
            {
                
                
            int l=1, r=n;
                
            while(l<=r) 
                
            {
                    
            int mid = (l+r)/2;
                    
            if( a > c[mid] && a <= c[mid+1] ) return mid+1// >&&<= 換為: >= && <
                    else if( a < c[mid] ) r = mid-1;
                    
            else l = mid+1;
                }

                
            }


            template
            <class T>
            int LIS(T a[], int n)
            {
                
                
            int i, j, size = 1;
                T 
            *c=new T[n+1];
                
            int *dp=new int[n+1];
                c[
            1= a[1]; dp[1= 1;
                
                
            for(i=2;i<=n;++i)
                
            {
                    
            if( a[i] <= c[1] ) j = 1;// <= 換為: <
                    else if( a[i] >c[size] )
                        j
            =++size;   // > 換為: >= 
                    else 
                        j 
            = bsearch(c, size, a[i]);
                    c[j] 
            = a[i]; dp[i] = j;
                }

                
            return size;
                
            }

            /////////////////////////END_TEMPLATE_BY_ABILITYTAO_ACM////////////////////////////

            下面是pku上有關LIS的題
            PKU 2533 ——Longest Ordered Subsequence 裸LIS,沒什么可說的
            #include<iostream>
            using namespace std;


            int a[2000];

            template
            <class T>
            int LIS(T a[],int n)
            {
                
            int i,j;
                
            int ans=1;
                
            int m=0;
                
            int *dp=new int[n+1];
                dp[
            1]=1;
                
            for(i=2;i<=n;i++)
                
            {
                    m
            =0;
                    
            for(j=1;j<i;j++)
                    
            {
                        
            if(dp[j]>m&&a[j]<a[i])
                            m
            =dp[j];
                    }

                    dp[i]
            =m+1;
                    
            if(dp[i]>ans)
                        ans
            =dp[i];
                }

                
            return ans;
            }










            int main ()
            {
                
            int n;
                
            int i;
                
            int finalmax=0;
                cin
            >>n;
                
            for(i=1;i<=n;i++)
                
            {
                    scanf(
            "%d",&a[i]);
                }

                printf(
            "%d\n" ,LIS(a,n));
                
            return 0;
            }





            PKU 1631——Bridging signals 這題用N^2算法要超時,必須使用NlogN的算法
            #include<iostream>
            #include
            <cstdio>
            using namespace std;


            const int N =  40000;
            int a[N];
            //最長上升子序列nlogn模板
            //入口參數:數組名+數組長度,類型不限,結構體類型可以通過重載運算符實現
            //數組下標從1號開始。
            /////////////////////////BEGIN_TEMPLATE_BY_ABILITYTAO_ACM////////////////////////////
            template<class T>
            int bsearch(T c[],int n,T a) 
            {
                
                
            int l=1, r=n;
                
            while(l<=r) 
                
            {
                    
            int mid = (l+r)/2;
                    
            if( a > c[mid] && a <= c[mid+1] ) return mid+1// >&&<= 換為: >= && <
                    else if( a < c[mid] ) r = mid-1;
                    
            else l = mid+1;
                }

                
            }


            template
            <class T>
            int LIS(T a[], int n)
            {
                
                
            int i, j, size = 1;
                T 
            *c=new T[n+1];
                
            int *dp=new int[n+1];
                c[
            1= a[1]; dp[1= 1;
                
                
            for(i=2;i<=n;++i)
                
            {
                    
            if( a[i] <= c[1] ) j = 1;// <= 換為: <
                    else if( a[i] >c[size] )
                        j
            =++size;   // > 換為: >= 
                    else 
                        j 
            = bsearch(c, size, a[i]);
                    c[j] 
            = a[i]; dp[i] = j;
                }

                
            return size;
                
            }

            /////////////////////////END_TEMPLATE_BY_ABILITYTAO_ACM////////////////////////////



            int main()
            {
                
            int testcase;
                
            int n;
                scanf(
            "%d",&testcase);
                
            int i,j;
                
            for(i=1;i<=testcase;i++)
                
            {
                    scanf(
            "%d",&n);
                    
            for(j=1;j<=n;j++)
                        scanf(
            "%d",&a[j]);
                    printf(
            "%d\n",LIS(a,n));
                }

                
            return 0;
            }



            PKU 1887——Testing the CATCHER 最長不升子序列,再次紀念下第一道動歸題
            Posted by abilitytao at 2008-09-25 00:50:48 on Problem 1887
            #include<iostream>
            #include
            <cmath>
            #include
            <cstdio>
            #include
            <cstring>
            using namespace std;


            int num[10000];
            int dp[10000];

            int main()
            {
                
            int n;
                
            int i,j;
                
            int len;
                
            int max;
                
            int finalmax;
                
            int flag=1;
                
            while(scanf("%d",&n))
                
            {
                    
            if(n==-1)
                        
            break;
                    num[
            0]=n;
                    
            for(i=1;;i++)
                    
            {
                        scanf(
            "%d",&n);
                        
            if(n==-1)
                            
            break;
                        
            else
                            num[i]
            =n;
                    }

                    len
            =i-1;

                    dp[len]
            =1;

                    
            for(i=len-1;i>=0;i--)
                    
            {
                        max
            =0;
                        
            for(j=i+1;j<=len;j++)
                        
            {
                            
            if(dp[j]>max&&num[j]<num[i])
                                max
            =dp[j];
                        }

                        dp[i]
            =max+1;
                    }

                    finalmax
            =0;
                    
            for(i=0;i<=len;i++)
                    
            {
                        
            if(dp[i]>finalmax)
                            finalmax
            =dp[i];
                    }

                    printf(
            "Test #%d:\n  maximum possible interceptions: %d\n\n",flag,finalmax);
                    flag
            ++;
                }

                
            return 0;
            }



            PKU 1609 Tiling Up Blocks 二維最長不下降子序列
            #include<iostream>
            #include
            <cstdlib>
            using namespace std;
            #define MAX 100001


            int dp[MAX];

            struct node
            {
                
            int a,b;
            }
            l[MAX];

            int cmp(const void *a,const void *b)
            {
                
            struct node c=(*(node*)a);
                
            struct node d=(*(node*)b);
                
            if(c.a!=d.a)
                    
            return c.a-d.a;
                
            else return c.b-d.b;
            }


            int main()
            {
                
            int n;
                
            int i,j;
                
            int maxnum;
                
            while(scanf("%d",&n))
                
            {
                    maxnum
            =1;
                    
            if(n==0)
                    
            {
                        printf(
            "*\n");
                        
            break;
                    }

                        
                    
            for(i=1;i<=n;i++)
                    
            {
                        scanf(
            "%d%d",&l[i].a,&l[i].b);
                    }

                    qsort(l
            +1,n,sizeof(l[1]),cmp);
                    dp[
            1]=1;
                    
            int temp;
                    
            for(i=2;i<=n;i++)
                    
            {
                        temp
            =0;
                        
            for(j=1;j<=i-1;j++)
                        
            {
                            
            if(dp[j]>temp&&l[i].a>=l[j].a&&l[i].b>=l[j].b)
                                temp
            =dp[j];
                        }

                        dp[i]
            =temp+1;
                        
            if(dp[i]>maxnum)
                            maxnum
            =dp[i];
                    }

                    printf(
            "%d\n",maxnum);
                }

                
            return 0;
            }


            本文為abilitytao原創 轉載請注明
            http://www.shnenglu.com/abilitytao/archive/2009/08/28/94693.html

            posted on 2009-08-28 19:09 abilitytao 閱讀(3857) 評論(4)  編輯 收藏 引用

            評論

            # re: 最長上升子序列LIS(Longest Increasing Subsequence) 2009-08-31 09:14

            總結得不錯,贊一個  回復  更多評論   

            # re: 最長上升子序列LIS(Longest Increasing Subsequence) 2009-09-07 18:14 jkfbaidu

            pku1631那個程序里,dp[]貌似沒起到作用……  回復  更多評論   

            # re: 最長上升子序列LIS(Longest Increasing Subsequence) 2009-09-07 18:56 abilitytao

            @jkfbaidu
            呵呵 的確是的 留著dp只是為了可能出現的情況而已  回復  更多評論   

            # re: 最長上升子序列LIS(Longest Increasing Subsequence) 2010-07-21 13:12 sosi

            我們用dp[i]來存放序列1-i的最長上升子序列的長度,這句話是錯誤的
            應但是以a[i]結尾的  回復  更多評論   

            99久久精品免费看国产| 亚洲AV伊人久久青青草原| 久久久黄色大片| 久久丝袜精品中文字幕| 久久免费小视频| 久久精品免费观看| 久久99精品综合国产首页| AV无码久久久久不卡蜜桃| 久久久久人妻一区精品性色av| 久久国产精品无| 人人妻久久人人澡人人爽人人精品| 日韩va亚洲va欧美va久久| 要久久爱在线免费观看| 亚洲国产精品成人久久蜜臀| 欧美色综合久久久久久| 伊人色综合久久天天网| 久久99精品久久久大学生| 久久夜色精品国产噜噜噜亚洲AV | 久久精品国产国产精品四凭| 国产三级观看久久| 久久青青草视频| 人妻精品久久无码区| 91精品观看91久久久久久| 日韩久久无码免费毛片软件 | 99久久精品免费| 久久综合色之久久综合| 亚洲综合熟女久久久30p| 99久久精品午夜一区二区 | 精品久久久久一区二区三区| 亚洲精品成人久久久| 亚洲精品无码成人片久久| 香港aa三级久久三级| 热99RE久久精品这里都是精品免费| 久久综合亚洲欧美成人| 久久国产精品免费| 精品国产乱码久久久久久郑州公司| 91久久精品国产91性色也| 无码精品久久久久久人妻中字| 婷婷综合久久中文字幕| 久久精品亚洲精品国产色婷| 久久亚洲国产成人影院网站 |