• <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

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

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

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

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

            //最長上升子序列(n^2)模板
            //入口參數(shù):1.數(shù)組名稱 2.數(shù)組長度(注意從1號(hào)位置開始)
            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):維護(hù)一個(gè)一維數(shù)組c,并且這個(gè)數(shù)組是動(dòng)態(tài)擴(kuò)展的,初始大小為1,c[i]表示最長上升子序列長度是i的所有子串中末尾最小的那個(gè)數(shù),根據(jù)這個(gè)數(shù)字,我們可以比較知道,只要當(dāng)前考察的這個(gè)數(shù)比c[i]大,那么當(dāng)前這個(gè)數(shù)一定能通過c[i]構(gòu)成一個(gè)長度為i+1的上升子序列。當(dāng)然我們希望在C數(shù)組中找一個(gè)盡量靠后的數(shù)字,這樣我們得到的上升子串的長度最長,查找的時(shí)候使用二分搜索,這樣時(shí)間復(fù)雜度便下降了。
            模板如下:

            //最長上升子序列nlogn模板
            //入口參數(shù):數(shù)組名+數(shù)組長度,類型不限,結(jié)構(gòu)體類型可以通過重載運(yùn)算符實(shí)現(xiàn)
            //數(shù)組下標(biāo)從1號(hào)開始。
            /////////////////////////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上有關(guān)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算法要超時(shí),必須使用NlogN的算法
            #include<iostream>
            #include
            <cstdio>
            using namespace std;


            const int N =  40000;
            int a[N];
            //最長上升子序列nlogn模板
            //入口參數(shù):數(shù)組名+數(shù)組長度,類型不限,結(jié)構(gòu)體類型可以通過重載運(yùn)算符實(shí)現(xiàn)
            //數(shù)組下標(biāo)從1號(hào)開始。
            /////////////////////////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 最長不升子序列,再次紀(jì)念下第一道動(dòng)歸題
            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原創(chuàng) 轉(zhuǎn)載請(qǐng)注明
            http://m.shnenglu.com/abilitytao/archive/2009/08/28/94693.html

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

            評(píng)論

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

            總結(jié)得不錯(cuò),贊一個(gè)  回復(fù)  更多評(píng)論   

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

            pku1631那個(gè)程序里,dp[]貌似沒起到作用……  回復(fù)  更多評(píng)論   

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

            @jkfbaidu
            呵呵 的確是的 留著dp只是為了可能出現(xiàn)的情況而已  回復(fù)  更多評(píng)論   

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

            我們用dp[i]來存放序列1-i的最長上升子序列的長度,這句話是錯(cuò)誤的
            應(yīng)但是以a[i]結(jié)尾的  回復(fù)  更多評(píng)論   


            只有注冊(cè)用戶登錄后才能發(fā)表評(píng)論。
            網(wǎng)站導(dǎo)航: 博客園   IT新聞   BlogJava   博問   Chat2DB   管理


            青青草国产精品久久| 欧美激情一区二区久久久| 91精品国产综合久久久久久| 少妇久久久久久被弄高潮| 国产亚洲精品自在久久| 国产精品久久久久一区二区三区| 成人精品一区二区久久久| 少妇被又大又粗又爽毛片久久黑人| 久久人妻AV中文字幕| 精品亚洲综合久久中文字幕| 久久这里有精品视频| 国产欧美久久久精品| 久久久久久毛片免费看| AV无码久久久久不卡蜜桃| 久久高清一级毛片| 97久久精品无码一区二区| 日韩欧美亚洲综合久久影院Ds| 亚洲乱码精品久久久久.. | 午夜视频久久久久一区| 天天躁日日躁狠狠久久| 久久久久亚洲AV成人网人人网站 | 99久久精品这里只有精品| 色播久久人人爽人人爽人人片AV| 7777久久久国产精品消防器材| 伊人色综合久久天天| 久久久免费精品re6| 欧美黑人激情性久久| 午夜精品久久久久9999高清| 久久综合丁香激情久久| 91精品国产色综合久久| 久久久久久九九99精品| 无码精品久久久久久人妻中字| 日本五月天婷久久网站| 2021久久精品免费观看| 2021国内精品久久久久久影院| 久久久久久无码国产精品中文字幕| 伊人久久综在合线亚洲2019| 亚洲国产精久久久久久久| 久久这里只有精品首页| 亚洲综合婷婷久久| 国产精品激情综合久久|