随笔-20  评论-16  文章-36  trackbacks-0

         最长递增子序列……看到和别人的巨大差距了,自已写了一个DP,感觉很麻烦,再看看别人的思路,感觉豁然开朗~~
         主要想法就是边找边修改,正确性我也反应了半天,才觉得设计的很巧妙,学习学习~~
         初始时len=0,len表示当前最长序列的长度-1(从0开始)。
         从前向后扫描输入数组,在a[0]~a[len]中找到最小的比a[i]大的元素位置(如果没有就是len+1)并将此元素替换成a[i],直到数组结尾,输出len+1。
         正确性:首先,很容易看出len<=i,因此不必另开数组,直接在原数组上操作,其次,根据替换规则,每个位置的元素都是所有该长度序列中可能的最小元素,否则可以找到一个更小的替换它,则对于最长的序列,它的长度不会缩短,而且由于是顺序扫描,最长序列的长度不会因为替换而增加,即不存在一种情况,使得把第i个元素替换后,导致原本不属于最长序列的元素加入到最长序列中来,否则,把该元素和前i个元素及最长序列的i+1~len个元素组成新的最长序列,与假设最长序列矛盾。
         故此算法产生的序列第i个元素为所有长度不小于i的序列的第i个位置最小元素,它的长度为最长序列的长度。
         下面是我的实现代码:

#include <iostream>
int main(){
    
int n, a[40001], p, i, l, h, mid, len;
    scanf(
"%d",&n);
    
while( n-- ){
        scanf(
"%d",&p);
        
for( i= 0; i< p; i++ )
            scanf(
"%d",&a[i]);
        len
= 0;
        
for( i= 1; i< p; i++ ){
            
if( a[i]> a[len] )
                a[
++len]= a[i];
            
else{
                l
= 0;
                h
= len;
                
while( l<= h ){
                    mid
= ( l+ h )/ 2;
                    
if( a[i]< a[mid] ) h= mid- 1;
                    
else l= mid+ 1;
                }

                a[l]
= a[i];
            }

        }

        printf(
"%d\n",len+1);
    }

    
return 0;
}
posted on 2009-04-22 21:20 古月残辉 阅读(258) 评论(0)  编辑 收藏 引用 所属分类: POJ

只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理