USCAO Buy Low, Buy Lower 4.3(dp)

题解说是最速下降问题,表示还没做到过,dp方程很好理解,关键是要求数量和同时不能重复,

NOCOW上的方法是

对于第二问求最长下降序列的数量,可以通过求第一问的过程解决。设MaxCnt[i]为第i项为末尾中最长下降序列的个数。

对于所有的j(1≤j≤i-1)如果有(s[j]>s[i] 并且 MaxLength[j]+1>MaxLength[i])则MaxCnt[i]=MaxCnt[j],否则如果(MaxLength[j]+1= =MaxLength[i])可利用加法原理,MaxCnt[i]=MaxCnt[i]+MaxCnt[j]。

考虑到题目中说的不能又重复的序列,我们可以增加一个域Next[i]表示大于i且离i最近的Next[i]使得第Next[i]个数与第i个数相同。如果不存在这样的数则Next[i]=0。这样我们在DP的时候如果出现Next[j]不为0且Next[j]<i可直接跳过。

这个题数据规模很大,用高精.

最后在末尾+个0,直接求到0的最长即可,记住长度最后-1.

一点碎碎念:昨天刚被老师怒骂一顿,唉,论文实在是不会弄了,硬着头皮上了。

/*

ID: hubiao cave

PROG: buylow

LANG: C++

*/




#include<iostream>

#include<fstream>

#include<string>
#include<cstring>
#include<vector>
using namespace std;


vector<string> ve;
int N;
long price[5002];
int nextp[5002];
ifstream fin("buylow.in");
ofstream fout("buylow.out");

//找的高精
class LLint
{
    private:
        const static int memLen=64;
        char mem[memLen];
        int  len;
    public:
        LLint()
    {
        memset(mem,0,sizeof(mem));
        len=0;
    }
    LLint(int n)
    {
        len=0;
        while(n)
        {
            mem[memLen-1-len++]=n%10+'0';
            n/=10;
        }
    }
    LLint(const LLint& rhs)
    {
        this->len=rhs.len;
        memcpy(this->mem,rhs.mem,memLen);
    }
    const LLint operator + (const LLint& rhs)
    {

        char buf[memLen]={0};
        memcpy(buf,this->mem,sizeof(this->mem));
        int Ex=0;
        int i;
        for(i=0;i<rhs.len;i++)
        {

            buf[memLen-1-i]=(buf[memLen-1-i]?buf[memLen-1-i]:'0')-'0'+rhs.mem[memLen-1-i]-'0'+Ex;
            if(buf[memLen-1-i]>=10)
                buf[memLen-1-i]=buf[memLen-1-i]-10+'0',Ex=1;
            else
                buf[memLen-1-i]+='0',Ex=0;
        }
        while(Ex)
        {
            buf[memLen-1-i]=(buf[memLen-1-i]?buf[memLen-1-i]:'0')-'0'+Ex;
            if(buf[memLen-1-i]>=10)
                buf[memLen-1-i]=buf[memLen-1-i]-10+'0',Ex=1;
            else
                buf[memLen-1-i]+='0',Ex=0;
            i++;
        }
        LLint l;
        if(buf[memLen-max(this->len,rhs.len)-1])
            l.len=max(this->len,rhs.len)+1;
        else
            l.len=max(this->len,rhs.len);
        memcpy(l.mem,buf,memLen);
        return l;
        
    }

    LLint& operator=(int n)
    {
        len=0;
        while(n)
        {
            mem[memLen-1-len++]=n%10+'0';
            n/=10;
        }
        return *this;
    }
    void print()
    {
        for(int i=len-1;i>=0;i--)
            fout<<mem[memLen-i-1];
        
    }
};

LLint cnt[5002];
int main()

{

    int m=1;
    fin>>N;
    for(int i=1;i<=N;++i)
        fin>>price[i];
    price[N+1]=0;

    for(int i=1;i<=N+1;++i)
        for(int j=i+1;j<=N+1;++j)
    {
        if(price[i]==price[j])
        {
            nextp[i]=j;
            break;
        }
    }
    int maxlen[5002];
    for(int i=1;i<=N+1;++i)
        maxlen[i]=1,cnt[i]=1;
    for(int i=2;i<=N+1;i++)
    {
        for(int j=1;j<i;j++)
        {
            if(nextp[j]&&nextp[j]<i)
                continue;
            if(price[i]<price[j])
            {
                if(maxlen[i]==maxlen[j]+1)
                    cnt[i]=cnt[i]+cnt[j];
                else if(maxlen[i]<maxlen[j]+1)
                    maxlen[i]=maxlen[j]+1,cnt[i]=cnt[j];
            }
        }
    }


    fout<<maxlen[N+1]-1<<" ";
    cnt[N+1].print();
    fout<<endl;
    return 0;


}

 

posted @ 2014-01-03 15:28  cavehubiao  阅读(154)  评论(0编辑  收藏  举报