[Acwing] 1068. 环形石子合并 区间DP

前言

传送门 : https://www.acwing.com/problem/content/1070/
没想到感冒一会,就两天没做题了,真恐怖QAQ

思路

朴素做法 : 对于n个点,我们需要合并n-1次,因此我们有n种方法进行合并,但是如果都枚举出来这n种 时间复杂度是 O ( n 4 ) O{(n^4)} O(n4) 会TLE

因此我们可以开 两倍数组 进行优化

CODE

#include 
using namespace std;
const int N  = 410 ,INF =0x3f3f3f3f;

int n;
int w[N],s[N];
int f[N][N],g[N][N];
void solve()
{
    cin>>n;
    for(int i=1;i<=n;i++)
    {
        cin>>w[i];
        w[i+n] = w[i];///两倍数组
    }

    for(int i=1;i<=n*2;i++)
    s[i] = s[i-1]+w[i]; ///预处理前缀和

    memset(f,0x3f,sizeof f);
    memset(g,-0x3f,sizeof g);

    for(int len = 1;len<=n;len++)
    {
        for(int l = 1;l+len-1<=n*2;l++)
        {
            int r = l+len-1;
            if(l == r) g[l][r] = f[l][r] = 0;///如果区间长度是1
            else
            {
                for(int k=1;k<r;k++)///状态转移i计算
                {
                     g[l][r] = max(g[l][r],g[l][k]+g[k+1][r]+s[r]-s[l-1]);

                     f[l][r] = min(f[l][r],f[l][k]+f[k+1][r]+s[r]-s[l-1]);
                }
            }
        }
    }

    int minv = INF ,maxv = -INF;
    for(int i=1;i<=n;i++)
    {
        minv =min(minv,f[i][i+n-1]);
        maxv =max(maxv,g[i][i+n-1]);
    }
    cout<<minv<<'\n'<<maxv<<'\n';
}



int main()
{
    ios::sync_with_stdio(false);
    solve();
    return 0;
}

你可能感兴趣的:(#,基础动态规划,动态规划,算法)