随笔-141  评论-9  文章-3  trackbacks-0

第一问,求最长下降子序列长度。

设a表示数据,len(i)=前i个数中最长下降子序列长度,状态转移方程 len (i)=max{len(j)+1}(j<i,a[j]>a[i]), 初始化f[i]=1 (i=0...n-1);

第二问:

对于c[i]=前i个数中最长下降子序列的个数,状态转移方程  c[i]=sigma(c[j]) (j<i,a[j]>a[i], len[i]==len[j]+1)

对于重复情况, 每一个可能重复的下降的子序列,它一定是a , b, b (a>b)的情况,开一个数组visited记录b是否出现过,若出现了,就不再计算。

状态转移方程: c[i]=sigma(c[j]) (j<i,a[j]>a[i], len[i]==len[j]+1),visited[j]=false)。

最后是高精度加法,我的版本是每一位存一个数,有待改进。

PS:这次代码风格有点变化。

/*
ID: lorelei3
TASK: buylow
LANG: C++
*/


#include 
<fstream>
#include 
<memory.h>

using namespace std;

const int  MAXN = 5000;
const int MAXP = 50;

class HPNum{
public:
    
int length;
    
int num[MAXP];

    HPNum()
{
        length
=1;
        memset(num,
0,sizeof(num));
    }


    
void plus(HPNum &p){
        
int len = length>p.length ? length : p.length;
        
for(int i=0; i<len; ++i){
            num[i] 
= num[i]+p.num[i];
            
if(num[i]>=10){
                num[i]
-=10;
                num[i
+1]++;
            }


        }

        
if(num[len]>0)
            len
++;
        length
=len;
    }

}
;

int n;
long maxlen;
long a[MAXN], len[MAXN];
bool visited[20000];
HPNum c[MAXN];

ifstream fin(
"buylow.in");
ofstream fout(
"buylow.out");

void input(){
    fin
>>n;
    
for(int i=0; i<n; ++i){
        fin
>>a[i];
        len[i]
=1;
    }

}


void dp(){
    
int i,j;
    maxlen
=1;
    
for(i=1; i<n; ++i)
        
for(j=i-1; j>=0--j){
            
if(a[i]<a[j] && len[i]<len[j]+1)
                len[i] 
= len[j]+1;
            
if(maxlen<len[i]) 
                maxlen 
= len[i];
        }

    
    
for(i=0; i<n; ++i)
        
if(len[i]==1){
            c[i].length
=1;
            c[i].num[
0]=1;
        }
else{
            memset(visited, 
falsesizeof(visited));
            
for(j=i-1; j>=0--j){
                
if(len[i]==len[j]+1 && !visited[a[j]] && a[i]<a[j]){
                    c[i].plus(c[j]);
                    visited[a[j]]
=true;
                }

            }

        }

}


void output(){
    
int i;
    HPNum sum;
    sum.length
=1;
    sum.num[
0]=0;
    memset(visited, 
falsesizeof(visited));
    
for(i=n-1; i>=0--i)
        
if(len[i]==maxlen && !visited[a[i]]){
            sum.plus(c[i]);
            visited[a[i]]
=true;
        }


    fout
<<maxlen<<" ";

    
for(i=sum.length-1; i>=0--i)
        fout
<<sum.num[i];

    fout
<<endl;
}


int main(){

    input();

    dp();

    output();
    
    
return 0;
}


 

posted on 2011-01-27 00:59 小阮 阅读(444) 评论(0)  编辑 收藏 引用 所属分类: USACO

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