[Jzoj] 3019. 序列和

题目大意

N N 个数排成一个环,请选出不超过 K K 段的连续的数,段与段间不能重叠,且
使得选出的数和最大

题目解析

D P DP
f [ i ] [ j ] [ 0 / 1 ] f[i][j][0/1] 表示第 i i 个数第 j j 段选或不选
f [ i ] [ j ] [ 0 ] = m a x ( f [ i 1 ] [ j ] [ 0 ] , f [ i 1 ] [ j ] [ 1 ] ) f[i][j][0]=max(f[i−1][j][0],f[i−1][j][1])
f [ i ] [ j ] [ 1 ] = m a x ( f [ i 1 ] [ j ] [ 1 ] , f [ i 1 ] [ j 1 ] [ 0 ] ) + a i f[i][j][1]=max(f[i−1][j][1],f[i−1][j-1][0])+a_i
a n s = m a x ( f [ i ] [ j ] [ 0 ] , f [ i ] [ j ] [ 1 ] ) ans=max(f[i][j][0],f[i][j][1])
但是这是个环,所以再求个最小值看看哪个优即可

代码

#include<bits/stdc++.h>
using namespace std;
int n,k,sum,maxn=-1e9,minn=1e9;
int a[100005],f[100005][12][2];
int main()
{
	cin>>n>>k;
	for(int i=1;i<=n;i++)
	 cin>>a[i],sum+=a[i];
	memset(f,-0x3f,sizeof(f));
	f[1][1][1]=a[1];
	f[1][0][0]=0;
	for(int i=2;i<=n;i++)
	 for(int j=0;j<=k;j++)
	 {
	   f[i][j][1]=max(f[i-1][j][1],f[i-1][j-1][0])+a[i];
	   f[i][j][0]=max(f[i-1][j][1],f[i-1][j][0]);
	   maxn=max(maxn,max(f[i][j][1],f[i][j][0]));
	 }
	memset(f,0x3f,sizeof(f));
	f[1][1][1]=a[1];
	f[1][0][0]=0;
	for(int i=2;i<=n;i++)
	 for(int j=0;j<=k;j++)
	 {
	   f[i][j][1]=min(f[i-1][j][1],f[i-1][j-1][0])+a[i];
	   f[i][j][0]=min(f[i-1][j][1],f[i-1][j][0]);
	   minn=min(minn,min(f[i][j][1],f[i][j][0]));
	 }
	cout<<max(maxn,sum-minn);
}

猜你喜欢

转载自blog.csdn.net/weixin_43909855/article/details/88760467
今日推荐