P3019 [JZOJ]序列和

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

样例 :

\(\texttt{Q:}\) 2 -1 2 -1 2 -4 1 -1 2

\(\texttt{A:}\) 7

我们要注意两个点,第一,这个是个 \(\texttt{DP}\)。其次这个是一个环。

我们设 \(f_{i,j,0/1}\) 代表在第 \(i\) 个数字中已经形成 \(j\) 个段,选不选第 \(i\) 个数字形成的最大值。首先是不选的情况,那么显然 :

\[f_{i,j,0}=\max\{f_{i-1,j,0},f_{i-1,j,1}\}\]

意思是我这个数字选和不选都不会影响 \(j\),且要求最大值所以要上一个数字选和不选的情况都要考虑。然后是选的情况 :

\[f_{i,j,1}=\max\{f_{i-1,j,1},f_{i-1,j-1,0}\}+num_i\]

首先解释一下为什么要 \(+num_i\),很显然,因为到了这个区间以后可能是负数,所以不用 \(max\{...,0\}\)。然后我们可以发现,如果上个数字选了那么现在就成了一段,段的数量不增加,\(f_{i-1,j,1}\)。如果上一个没有选,我单独成段,由 \(j-1\) 变成 \(j\),\(f_{i-1,j-1,0}\)

环怎么搞?暴力?

其实我们可以看一个图 :

e591cbd36389acbd93fc2.png

如果这是一个环,那么最前面的段和最后面的段就都是段 \(1\)。那么我们是不是只要把 \(\{2,4,6\}\) 的值求出来,用全部减去它就可以了。然后要考虑可能环的情况不是最优,所以要用不是环的情况也做一遍。

Uses math;

Const
    total_1=100000 << 1;
    total_2=10 << 1;

var
    fuck:array[-1..total_1,-1..total_2,0..1] of longint;
    num:array[-1..total_1] of longint;
    i,j,k,n,m,sum,maxn,minn:longint;
begin
    read(n,m); maxn:=-maxlongint; minn:=maxlongint;
    for i:=1 to n do begin read(num[i]); inc(sum,num[i]); end;
    for i:=1 to n do for j:=1 to m do for k:=0 to 1 do fuck[i,j,k]:=-maxlongint div 8;
    fuck[1,1,1]:=num[1 ]; fuck[1,0,0]:=0;
    for i:=2 to n do for j:=1 to m do
        begin
            fuck[i,j,0]:=max(fuck[i-1,j,0],fuck[i-1,j,1]);
            fuck[i,j,1]:=max(fuck[i-1,j,1],fuck[i-1,j-1,0])+num[i];
            maxn:=max(fuck[i,j,0],fuck[i,j,1]);
        end;
    for i:=1 to n do for j:=1 to m do for k:=0 to 1 do fuck[i,j,k]:=maxlongint div 8;
    fuck[1,1,1]:=num[1]; fuck[1,0,0]:=0;
    for i:=2 to n do for j:=1 to m do 
        begin
            fuck[i,j,0]:=min(fuck[i-1,j,0],fuck[i-1,j,1]);
            fuck[i,j,1]:=min(fuck[i-1,j,1],fuck[i-1,j-1,0])+num[i];
            minn:=min(fuck[i,j,0],fuck[i,j,1]);
        end;
    writeln(max(sum-minn,maxn));
end.

转载于:https://www.cnblogs.com/FibonacciHeap/articles/10584309.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值