动态规划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\n",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\n",res);
    }
    return 0;
}

  

posted @ 2020-03-16 22:06  东坡肉肉君  阅读(198)  评论(0编辑  收藏  举报