很明显的一道区间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;
}
原文:https://www.cnblogs.com/loney-s/p/11861154.html