zoukankan      html  css  js  c++  java
  • YBT 5.1 区间类动态规划

    题解在代码中

    石子合并[loj 10147]

    /* 
    dp[i][j]=max or min(dp[i][j],dp[i][k]+dp[k+1][j]+sum[j]-sum[i-1]) 
    i<=k<j 
    */ 
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    using namespace std;
    inline int read()
    {
        int f=1,ans=0;char c;
        while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
        while(c>='0'&&c<='9'){ans=ans*10+c-'0';c=getchar();}
        return f*ans;
    }
    int a[401],n,dp_minn[401][401],dp_maxn[401][401],sum[401];
    int main()
    {
        memset(dp_minn,127,sizeof(dp_minn));
        n=read();
        for(int i=1;i<=n;i++) 
        {
            dp_minn[i][i]=dp_minn[i+n][i+n]=0;
            a[i]=read(),a[i+n]=a[i];
        }
        for(int i=1;i<=2*n;i++) sum[i]=sum[i-1]+a[i];
        for(int t=2;t<=n;t++)
            for(int i=1;i<=2*n&&i+t-1<=2*n;i++)
            {
                int j=i+t-1;
                
                for(int k=i;k<j;k++)
                {
                    dp_maxn[i][j]=max(dp_maxn[i][j],dp_maxn[i][k]+dp_maxn[k+1][j]+sum[j]-sum[i-1]);
                    dp_minn[i][j]=min(dp_minn[i][j],dp_minn[i][k]+dp_minn[k+1][j]+sum[j]-sum[i-1]);
                }//cout<<i<<" "<<j<<" "<<dp_minn[i][j]<<endl;
            }
        int maxn=0,minn=2<<30-1;
        for(int i=1;i<=n;i++) maxn=max(maxn,dp_maxn[i][i+n-1]),minn=min(minn,dp_minn[i][i+n-1]);
        cout<<minn<<endl<<maxn; 
    }
    View Code

    能量项链[loj 10148]

    /*
    为了好想 记录每一的head和tail
    so dp[i][j]=max(dp[i][j],dp[i][k]+dp[k+1][j]+head[i]*tail[k]*tail[j])  
    i<=k<j
    */ 
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    using namespace std;
    inline long long read()
    {
        long long f=1,ans=0;char c;
        while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
        while(c>='0'&&c<='9'){ans=ans*10+c-'0';c=getchar();}
        return f*ans;
    }
    long long dp[201][201],a[201],h[201],t[201];
    int main()
    {
        long long n=read();
        for(long long i=1;i<=n;i++) a[i]=read(),a[i+n]=a[i];
        for(long long i=1;i<2*n;i++) h[i]=a[i],t[i]=a[i+1];
    //    for(int i=1;i<2*n;i++) cout<<h[i]<<" "<<t[i]<<endl;
        for(long long tt=1;tt<n;tt++)
            for(long long i=1;i<=2*n&&i+tt<=2*n;i++)
            {
                long long j=i+tt;
    //            cout<<i<<" "<<j<<endl;
                for(long long k=i;k<j;k++) dp[i][j]=max(dp[i][j],dp[i][k]+dp[k+1][j]+h[i]*t[k]*t[j]);
            }
        long long maxn=0;
        for(long long i=1;i<=n;i++) maxn=max(maxn,dp[i][i+n-1]); 
        cout<<maxn;
    }
    /*
    7
    23 17 212 113 71 301 33 
    31182687
    */
    View Code

    凸多边形的划分[loj 10149]

    /*
    高精度或__int128
    dp[i][j]=min(dp[i][j],dp[i][k]+dp[k][j]+a[i]*a[k]*a[j]) 
    dp[i][j][0]存位数
    其他四个数一个int 
    */
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    using namespace std;
    inline long long read()
    {
        long long f=1,ans=0;char c;
        while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
        while(c>='0'&&c<='9'){ans=ans*10+c-'0';c=getchar();}
        return ans*f;
    }
    long long n,a[51]; 
    long long dp[110][110][110];
    long long s1[110],s2[110],s3[110];
    void print()
    {
        cout<<dp[1][n][dp[1][n][0]];
        for(long long i=dp[1][n][0]-1;i>=1;i--)
        {
            cout<<dp[1][n][i]/1000;
            cout<<dp[1][n][i]/100%10;
            cout<<dp[1][n][i]/10%10;
            cout<<dp[1][n][i]%10;
        }
    }
    void mark(long long c[])
    {
        for(long long i=1;i<=c[0];i++)
        {
            c[i+1]+=c[i]/10000;
            c[i]%=10000;
        }
        while(c[c[0]+1]!=0)
        {
            c[0]++;
            c[c[0]+1]=c[c[0]]/10000;
            c[c[0]]%=10000;
        }
    }
    void mul(long long a1,long long a2,long long a3,long long c[])
    {
        c[0]=c[1]=1;
        for(long long i=1;i<=c[0];i++) c[i]*=a1;
        mark(c);
        for(long long i=1;i<=c[0];i++) c[i]*=a2;
        mark(c);
        for(long long i=1;i<=c[0];i++) c[i]*=a3;
        mark(c);
    }
    void add(long long a[],long long b[],long long c[])
    {
        if(a[0]>b[0]) c[0]=a[0];
        else c[0]=b[0];
        for(long long i=1;i<=c[0];i++) c[i]=a[i]+b[i];
        mark(c);
    }
    long long compare(long long a[],long long b[])
    {
        if(a[0]>b[0]) return 1;
        if(a[0]<b[0]) return 0;
        for(long long i=a[0];i>=1;i--)
        {
            if(a[i]<b[i]) return 0;
            else if(a[i]>b[i]) return 1;
        }
        return 0;
    }
    int main()
    {
        n=read();
        for(long long i=1;i<=n;i++) a[i]=read();
        for(long long t=2;t<=n-1;t++)
        {
            for(long long i=1;i+t<=n;i++)
            {
                long long j=i+t;
                dp[i][j][0]=60;
                for(long long k=i+1;k<=j-1;k++)
                {
                    memset(s1,0,sizeof(s1));
                    memset(s2,0,sizeof(s2));
                    memset(s3,0,sizeof(s3));
                    mul(a[i],a[k],a[j],s1);
                    add(dp[i][k],dp[k][j],s2);
                    add(s1,s2,s3);
                    if(compare(dp[i][j],s3))
                        memcpy(dp[i][j],s3,sizeof(s3));
                }
            }
        }
        print();
    }
    View Code

    括号配对[loj 10150]

    /*
    dp[i][j]表示在[i,j]中至少需要添加的数量
    1.  (i==[  j==] )  or(i==(   j==))  dp[i][j]=min(dp[i][j],dp[i+1][j-1]
    2.  i==( or  i==[ dp[i][j]=min(dp[i][j],dp[i+1][j])
    3.  j==) or j==]  dp[i][j]=min(dp[i][j],dp[i][j-1])
    4. dp[i][j]=min(dp[i][j],dp[i][k]+dp[k+1][j]) (i<=k<j) 
    
    
    初始化时dp[i][j]=inf  (i<=j) dp[i][i]=1;(1<=i<=n)
    想一想为什么 
    */ 
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    using namespace std;
    inline int read()
    {
        int f=1,ans=0;char c;
        while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
        while(c>='0'&&c<='9'){ans=ans*10+c-'0';c=getchar();}
        return f*ans;
    }
    char str[102];
    int a[102];
    int dp[110][110],inf=2<<30-1;
    int main()
    {
    //    memset(dp,127,sizeof(dp));
        
        scanf("%s",str+1);
        int len=strlen(str+1);
        for(int i=1;i<=len;i++)
            for(int j=i;j<=len;j++) dp[i][j]=inf;
        for(int i=1;i<=len;i++) 
        {
            dp[i][i]=1;
            if(str[i]=='(') a[i]=1;
            if(str[i]==')') a[i]=2;
            if(str[i]=='[') a[i]=3;
            if(str[i]==']') a[i]=4;
        }
        for(int t=1;t<len;t++)
        {
            for(int i=1;i+t<=len;i++)
            {
                int j=i+t;
                if((a[i]==1&&a[j]==2)||(a[i]==3&&a[j]==4)) dp[i][j]=min(dp[i][j],dp[i+1][j-1]);
                if(a[i]==1||a[i]==3) dp[i][j]=min(dp[i][j],dp[i+1][j]+1);
                if(a[j]==2||a[j]==4) dp[i][j]=min(dp[i][j],dp[i][j-1]+1);
                for(int k=i;k<j;k++) dp[i][j]=min(dp[i][j],dp[i][k]+dp[k+1][j]);
    //            cout<<i<<" "<<j<<" "<<dp[i][j]<<endl;
            }
        }
        cout<<dp[1][len];
    }
    View Code

    分离与合体[loj 10151]

    /*
    dp[i][j]=max(dp[i][j],dp[i][k]+dp[k+1][j]+(a[i]+a[j])*a[k])
    i<=k<j
    
    用last记录
    bfs保证了一分为二,二分为四的输出 
    */ 
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    #include<queue>
    using namespace std;
    inline int read()
    {
        int f=1,ans=0;char c;
        while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
        while(c>='0'&&c<='9'){ans=ans*10+c-'0';c=getchar();}
        return f*ans;
    }
    int n,a[301],dp[301][301],last[301][301];
    void bfs()
    {
        queue< pair <int,int > > que;
        que.push(make_pair(1,n));
        while(!que.empty())
        {
            pair<int,int> s=que.front();
            que.pop();
            if(s.first==s.second) continue;
            cout<<last[s.first][s.second]<<" ";
            que.push(make_pair(s.first,last[s.first][s.second]));
            que.push(make_pair(last[s.first][s.second]+1,s.second));
        }
    }
    int main()
    {
        n=read();
        for(int i=1;i<=n;i++) a[i]=read();
        for(int t=1;t<n;t++)
            for(int i=1;i+t<=n;i++)
            {
                int j=i+t;
                for(int k=j-1;k>=i;k--) 
                {
                    int t=dp[i][k]+dp[k+1][j]+(a[i]+a[j])*a[k];
                    if(t>=dp[i][j])
                    {
                        dp[i][j]=max(dp[i][j],dp[i][k]+dp[k+1][j]+(a[i]+a[j])*a[k]);
                        last[i][j]=k;
                    }
                }
            }
        cout<<dp[1][n]<<endl;
        bfs();
        return 0;
    }
    View Code

    矩阵取数游戏[loj 10152]

    /*
    一行一行处理 
    dp[i][j]表示变到 i,j时的最大分数 
    dp[i][j]=max(dp[i][j],dp[i-1][j]*a[i-1]^pow(2,n+i-j-1),dp[i][j+1]*a[j+1]^pow(2,n+i-j-1)) 
    */ 
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    using namespace std;
    inline long long read()
    {
        long long f=1,ans=0;char c;
        while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
        while(c>='0'&&c<='9'){ans=ans*10+c-'0';c=getchar();}
        return f*ans;
    }
    
    __int128 dp[101][101],ans,sry[101];
    long long n,m,a[101];
    void print(__int128 x)
    {
        if(x==0) return;
        else if(x!=0) print(x/10);
        putchar(x%10+'0');
    }
    int main()
    {
        sry[0]=1;
        for(int i=1;i<=100;i++) sry[i]=sry[i-1]*2;
        n=read(),m=read();
        for(long long i=1;i<=n;i++)
        {
            for(long long j=1;j<=m;j++) a[j]=read();
            memset(dp,0,sizeof(dp));
            for(long long i=1;i<=m;i++)
                for(long long j=m;j>=i;j--) 
                    dp[i][j]=max(dp[i-1][j]+a[i-1]*sry[m-j+i-1],dp[i][j+1]+a[j+1]*sry[m-j+i-1]);
            __int128 maxn=-1;
            for(long long i=1;i<=m;i++) maxn=max(maxn,dp[i][i]+a[i]*sry[m]);
            ans+=maxn;
        }
        if(ans==0) 
        {
            cout<<0;return 0;}
        print(ans);
    }
    View Code
  • 相关阅读:
    设计模式之访问者模式
    设计模式之命令模式
    设计模式之迭代器模式
    tomcat8.0.11性能优化
    java 基础 --集合--012
    StringBuffer和StringBuilder的区别
    jquery 入门
    java 基础 --匿名内部类-008
    java 基础 --多态--009
    java 基础--继承--007
  • 原文地址:https://www.cnblogs.com/si-rui-yang/p/9502515.html
Copyright © 2011-2022 走看看