zoukankan      html  css  js  c++  java
  • CodeForces 23E ,77C,455A,437E,245H

    五天每天刷了一dp

     定义 :dp[i]为取前i个元素后得到的最大值。则dp[i]=max(dp[i-1],dp[i-2]+a[i]*i);

    写的时候愚蠢的分类讨论i元素是否选取。实际上第i-2个元素是否选取和状态dp[i]无关

    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    using namespace std;
    #define ll __int64
    const int maxn=100000;
    ll a[maxn+8];
    ll  dp[maxn+8][2];
    int main()
    {
        int i,j,k,n;
        scanf("%d",&n);
        memset(a,0,sizeof(a));
        memset(dp,0,sizeof(dp));
        for(i=1;i<=n;i++)
        {
            scanf("%d",&k);
            a[k]++;
        }
        int x,y;
        for(i=1;i<=maxn;i++)
        {
            if(a[i]==0)
                dp[i][1]=max(dp[i-1][1],dp[i-1][0]);
            else
                dp[i][1]=max(dp[i-1][0]+a[i]*i,dp[i-1][1]);
            dp[i][0]=dp[i-1][1];
        }
        printf("%I64d
    ",dp[maxn][1]);
        return 0;
    }

    CodeForces 245H  Queries for Number of Palindromes

    给定一个字符串,q个询问,每个询问这个区间内有多少个回文串

    区间dp统计数目即可

    定义dp[i][j]为i到j的回文串总数

    若s[i]==s[j]并且i+1~j-1段为回文串  dp[i][j]=dp[i][j-1]+dp[i+1][j]-dp[i+1][j-1]+1;

    否则dp[i][j]=dp[i][j-1]+dp[i+1][j]-dp[i+1][j-1];

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    const int maxn=5008;
    char s[maxn];
    int dp[maxn][maxn];
    bool papa[maxn][maxn];
    int main()
    {
            int q;
        int i,j,k,n,m;
         scanf("%s",s+1);
         int len=strlen(s+1);
         memset(dp,0,sizeof(dp));
         memset(papa,false,sizeof(papa));
         for(i=1;i<=len;i++)
         {    dp[i][i]=1;papa[i][i]=true;} 
         for(i=1;i<len;i++)
         {
             if(s[i]==s[i+1])
             {
                 dp[i][i+1]=3;
                 papa[i][i+1]=true;
             }
             else
                 dp[i][i+1]=2;
                 } 
         for(k=2;k<len;k++)
         {
             for(i=1;i+k<=len;i++)
             {
                 if(s[i]==s[i+k]&&papa[i+1][i+k-1]==true)    
                 {
                 dp[i][i+k]=dp[i][i+k-1]+dp[i+1][i+k]+1-dp[i+1][i+k-1];
                 papa[i][i+k]=true;
                }
                 else    dp[i][i+k]=dp[i][i+k-1]+dp[i+1][i+k]-dp[i+1][i+k-1];
             }
        }
         scanf("%d",&q);
         while(q--)
         {
             scanf("%d%d",&n,&m);
             printf("%d
    ",dp[n][m]);
         }
         return 0;
    }

    CodeForces 437E  The Child and Polygon

    给定一个多边形求在题目条件下分割方式一共有多少种

    依然区间dp统计个数.先把点都化成顺时针,若i,j之间的点k满足向量jk在向量ji的顺时针方,则dp[i][j]+=dp[i][k]*dp[k][j];

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    #define ll __int64
    const int maxn=208;
    const int mod=1e9+7;
    struct poi{
        ll x,y;
        ll operator * (const poi &a)    const
        {
            return x*a.y-y*a.x;
        }
        poi operator - (const poi &a)    const
        {
            poi u;
            u.x=x-a.x;
            u.y=y-a.y;
            return u;
        }
    }f[maxn];
    ll dp[maxn][maxn];
    ll    medp(int x,int y)
    {
        if(dp[x][y]!=-1)    return dp[x][y];
        if(y-x==1)    return dp[x][y]=1;
        ll ans=0;
        for(int i=x+1;i<y;i++)
            if((f[x]-f[y])*(f[i]-f[y])>0)
                ans=(ans+medp(x,i)*medp(i,y))%mod;
        dp[x][y]=ans;
        return ans;
    }
    int main()
    {
        int i,j,n;
        scanf("%d",&n);
        for(i=1;i<=n;i++)
            scanf("%I64d%I64d",&f[i].x,&f[i].y); 
        ll ans=0;
        for(i=1;i<n;i++)
        {
            ans+=f[i]*f[i+1];
        }
        ans+=f[n]*f[1];
        if(ans<0)
        {
            poi shit;
            for(i=1;i<=(n>>1);i++)
            {
                shit=f[i];
                f[i]=f[n-i+1];
                f[n-i+1]=shit;
            }    
        }
        memset(dp,-1,sizeof(dp)); 
        medp(1,n);
        printf("%I64d
    ",dp[1][n]);
        return 0;    
    }

    CodeForces 77C  Beavermuncher-0xFF    

    没想到用优先队列优化。代码不贴了。

    对于弱的神题,——
    看了某神牛的代码,高精度模板很漂亮

    主算法竟然一个后序遍历思想解决,学习了

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    const int mod=10000;
    const int st=80;
    const int maxn=710;
    const int maxm=2010;
    int pre[maxm],last[maxm],other[maxm],s[maxm];
    int tot,n;
    struct bigint{
        int a[st],n;
        bigint(){
        };
        bigint(int x)
        {
            memset(a,0,sizeof(a));
            n=1,a[0]=x;
        }
        void init(int x)
        {
            n=1,a[0]=x;
        }
        bool operator<(const bigint &x)
        {
            if(n<x.n)    return 1;
            else    if(n>x.n)    return 0;
            for(int i=n-1;i>=0;i--)
                if(a[i]<x.a[i])    return 1;
                else    if(a[i]>x.a[i])    return 0;
            return 0;
        }
        bigint operator * (const bigint &x)
        {
            bigint t(0);t.n=x.n+n-1;
            for(int i=0;i<n;i++)
                for(int j=0;j<x.n;j++)
                    t.a[i+j]+=a[i]*x.a[j];
            for(int i=0;i<t.n;i++)
            {
                t.a[i+1]+=t.a[i]/mod;
                t.a[i]%=mod;
            }    
            if(t.a[t.n])    t.n++;
            return t;
        }
        bigint operator + (const bigint x)
        {
            bigint t(0);t.n=max(x.n,n);
            for(int i=0;i<t.n;i++)
            {
                t.a[i]=t.a[i]+x.a[i]+a[i];
                t.a[i+1]+=t.a[i]/mod;
                t.a[i]%=mod;
            }
            if(t.a[t.n])    ++t.n;
            return t;
        }
        void print(){
            printf("%d",a[n-1]);
            for(int i=n-2;i>=0;i--)
                printf("%04d",a[i]);
            puts(" ");
        }
    }dp[maxn][maxn];
    void add(int p,int q)
    {
        pre[++tot]=last[p];
        last[p]=tot;
        other[tot]=q;
    }
    void dfs(int i,int f)
    {
        s[i]=1,dp[i][1].init(1),dp[i][0].init(0);
        for(int j=last[i];j;j=pre[j])
        {
            int k=other[j];
            if(k==f)    continue;
            dfs(k,i);
            for(int p=s[i];p>=0;p--)
            {
                for(int q=s[k];q>=0;q--)
                {
                    bigint c=dp[i][p]*dp[k][q];
                    if(dp[i][p+q]<c)    dp[i][p+q]=c;
                }
            }
            s[i]+=s[k];
        }
        for(int p=1;p<=s[i];p++)
        {
            bigint c(p);
            c=c*dp[i][p];
            if(dp[i][0]<c)    dp[i][0]=c;
        }
    }
    int main()
    {
        int i,j,u,v;
        scanf("%d",&n);
        for(i=1;i<n;i++)
        {
            scanf("%d%d",&u,&v);
            add(u,v);add(v,u);
        }
        dfs(1,0);
        dp[1][0].print();
        return 0;
    }
  • 相关阅读:
    org.springframework.beans.factory.BeanCreationException
    线程浅谈
    第五次作业
    第四次作业
    第三次作业
    第二次作业
    第一次作业
    第五次作业
    第三次作业
    第二次作业
  • 原文地址:https://www.cnblogs.com/bitch1319453/p/4712709.html
Copyright © 2011-2022 走看看