题目:分蛋糕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;
}	

posted @ 2019-11-14 20:01  loney_s  阅读(197)  评论(0)    收藏  举报