题目:分蛋糕2(区间DP)

题目

传送门

思路

很明显的一道区间DP的板子题目
\(dp[i][j]\)是左端点i到右端点j,LOJ君取得最大值
转移很简单
就是考虑左端点和右端点了
细节不多,就一个破环成链

代码

#include<iostream>
#include<cstdio>
using namespace std;
#define int long long
void read(long long &x)
{
    x=0;
    long long f=1;
    char c=getchar();
    while('0'>c||c>'9')
    {
        if(c=='-')
            f=-1;
        c=getchar();
    }
    while('0'<=c&&c<='9')
    {
        x=(x<<3)+(x<<1)+c-'0';
        c=getchar();
    }
    x*=f;
}
long long n;
long long ans;
long long a[4005];
long long dp[4005][4005];//左端点为i,右端点为j,
void update(int &l,int &r)
{
    if(l==0)
        l=n;
    if(r==n+1)
        r=1;
}
long long dfs(int l,int r,int f)
{
    if(l>r)
        return 0; 
    if(f==0)
    {
        if(a[l]>a[r])
            l++;
        else 
            r--;
        return dfs(l,r,f^1); 
    }
    else
    {
        if(dp[l][r])
            return dp[l][r];
        dp[l][r]=max(dp[l][r],dfs(l+1,r,f^1)+a[l]);
        dp[l][r]=max(dp[l][r],dfs(l,r-1,f^1)+a[r]);
        return dp[l][r];
    }
}
signed main()
{
    read(n);
    for(int i=1;i<=n;i++)
    {
        read(a[i]);
        dp[i][i]=a[i];
    }
    for(int i=n+1;i<=2*n;i++)
    {
        if(i%n==0)
            a[i]=a[2*n];
        else
            a[i]=a[i%n];
        dp[i][i]=a[i];
    }
    for(int i=1;i<=n;i++)
    {
        long long x=a[i];
        int l=i-1;
        int r=i+1;
        update(l,r);
        if(l<r)
            ans=max(ans,dfs(r,l+n,0)+x);
        else
            ans=max(ans,dfs(r,l,0)+x);
    }
    cout<<ans;
    return 0;
}   

猜你喜欢

转载自www.cnblogs.com/loney-s/p/11861154.html