• 动态规划3(区间+树形)


    石子合并问题--直线版 HRBUST - 1818 

    注释的部分是平行四边形优化,下面是分析的草稿

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    using namespace std;
    const int INF = 0x3f3f3f3f;
    const int N = 300;
    int sum[N],n;
    int Minval()
    {
        int dp[N][N];memset(dp,INF,sizeof(dp));
        for(int i=1;i<=n;++i) dp[i][i]=0;
        for(int len=1;len<n;++len)
            for(int i=1;i<=n-len;++i)
            {
                int j=i+len;
                for(int k=i;k<j;k++)
                   dp[i][j]=min(dp[i][j],dp[i][k]+dp[k+1][j]+sum[j]-sum[i-1]);
            }
        printf("%d ",dp[1][n]);
        return dp[1][n];
    }
    int Maxval()
    {
        int dp[N][N]; memset(dp,0,sizeof(dp));
        for(int i=1;i<=n;++i) dp[i][i]=0;
        for(int len=1;len<n;++len)
            for(int i=1;i<=n-len;++i)
            {
                int j=i+len;
                for(int k=i;k<j;k++)
                   // dp[i][j]=min(dp[i][k]+dp[k+1][j])+sum[j]-sum[i];同时扩大再取小,对结果没影响
                    dp[i][j]=max(dp[i][j],dp[i][k]+dp[k+1][j]+sum[j]-sum[i-1]);
            }
        printf("%d
    ",dp[1][n]);
        return dp[1][n];
    }
    int main()
    {
        while(cin>>n)
        {
            sum[0]=0;
            for(int i=1;i<=n;++i)
            {
                int x;
                cin>>x;
                sum[i]=sum[i-1]+x;//sum[i]代表 1-i所有数字的和
            }
            Minval();
            Maxval();
        }
        return 0;
    }
    //int Minval()
    //{
    //    int dp[N][N];
    //    for(int i=1;i<=n;++i) { dp[i][i]=0; s[i][i]=i;   }
    //    for(int len=1;len<n;++len)
    //        for(int i=1;i<=n-len;++i)
    //        {
    //            int j=i+len;
    //            dp[i][j]=INF;
    //            for(int k=s[i][j-1];k<=s[i+1][j];k++)
    //               // dp[i][j]=min(dp[i][k]+dp[k+1][j])+sum[j]-sum[i];同时扩大再取小,对结果没影响
    //                if(dp[i][j]>dp[i][k]+dp[k+1][j]+sum[j]-sum[i-1])
    //                {
    //                    dp[i][j]=dp[i][k]+dp[k+1][j]+sum[j]-sum[i-1];
    //                    s[i][j]=k;
    //                }
    //        }
    //    return dp[1][n];
    //}  

    B - Cheapest Palindrome[回文串]

    #include<iostream>
    using namespace std;
    int w[30],n,m,dp[2005][2005];
    char s[2005],ch;
    int main()
    {
        int x,y;
        while(cin>>n>>m)
        {
            cin>>s;
            for(int i=0;i<n;++i)
            {
                cin>>ch>>x>>y;
                w[ch-'a']=min(x,y);
            }
            for(int i=m-1;i>=0;i--)
            {
                for(int j=i+1;j<m;++j)
                {
                    if(s[i]==s[j])
                    {
                        dp[i][j]=dp[i+1][j-1];
                    }
                    else
                    {
                        dp[i][j]=min(dp[i+1][j]+w[s[i]-'a'],dp[i][j-1]+w[s[j]-'a']);
                    }
                }
            }
            cout<<dp[0][m-1]<<endl;
        }
        return 0;
    }
    

    C - Monkey Party[平行四边形]

    #include<iostream>
    #include<cstring>
    #include<stdio.h>
    #define INF 0x3f3f3f3f
    using namespace std;
    const int N = 1e4;
    int n,m;
    int dp[N][N],sum[N],w[N];
    int main()
    {
        while(cin>>m)
        {
            for(int i=1;i<=m;++i)
            {
                cin>>w[i];
                sum[i]=sum[i-1]+w[i];
            }
            n=m*2;
            for(int i=m+1,j=1;i<=n;++i,++j)
            {
    //            cout<<sum[i]<<","<<w[j]<<endl;
                sum[i]=sum[i-1]+w[j];
            }
            memset(dp,INF,sizeof(dp));
            for(int i=1;i<=n;++i) dp[i][i]=0;
            for(int len=1;len<n;++len)
                for(int i=1;i<=n-len;++i)
                {
                    int j=i+len;
                    for(int k=i;k<j;k++)
                       dp[i][j]=min(dp[i][j],dp[i][k]+dp[k+1][j]+sum[j]-sum[i-1]);
                }
            printf("%d",dp[1][m]);
        }
        return 0;
    }
    不用平行四边形导致超时
    #include<iostream>
    #include<cstring>
    #include<stdio.h>
    #define INF 0x3f3f3f3f
    using namespace std;
    const int N =  2e3 + 10;
    int n,m;
    int dp[N][N],sum[N],p[N][N],w[N];
    int main()
    {
        while(cin>>m)
        {
            for(int i=1;i<=m;++i)
            {
                cin>>w[i];
                sum[i]=sum[i-1]+w[i];
            }
            n=m*2;
            for(int i=m+1,j=1;i<=n;++i,++j)
            {
                sum[i]=sum[i-1]+w[j];
            }
            memset(dp,0,sizeof(dp));
            memset(p,0,sizeof(p));
            for(int i=1;i<=n;++i) { dp[i][i]=0;p[i][i]=i; }
            for(int len=1;len<n;++len)
                for(int i=1;i<=n-len;++i)
                {
                    int j=i+len;dp[i][j]=INF;
                    for(int k=p[i][j-1];k<=p[i+1][j];k++)
                       if(dp[i][j]>dp[i][k]+dp[k+1][j]+sum[j]-sum[i-1])
                       {
                           dp[i][j]=dp[i][k]+dp[k+1][j]+sum[j]-sum[i-1];
                           p[i][j]=k;
                       }
                }
            int res = INF;
            for (int i = 1; i <= m; i++) {
                res = min(res,dp[i][i + m - 1]);
            }
            printf("%d
    ",res);
        }
        return 0;
    }
    

      

  • 相关阅读:
    PHP Cookies
    PHP 文件上传
    PHP 文件
    02_电话拨号器intent说明
    13_传智播客iOS视频教程_OC程序的编译链接
    12_传智播客iOS视频教程_注释和函数的定义和调用
    11_传智播客iOS视频教程_NS前缀和@符号
    10_传智播客iOS视频教程_NSString
    09_传智播客iOS视频教程_自动释放池与NSLog函数
    08_传智播客iOS视频教程_Foundation框架
  • 原文地址:https://www.cnblogs.com/chrysanthemum/p/12507224.html
Copyright © 2020-2023  润新知