[apio2010]特别行动队(斜率优化的dp)

本文探讨了一种使用动态规划、斜率优化和单调队列优化方法解决序列分组问题,以最大化每份的收益。通过变形公式和变量转换,简化了原问题并实现了高效求解。

[题目简述]

        给你一个序列,你要将他们分成连续的若干份.每一份带给你的收益是ax^2+bx+c,其中x是这一份的和,a<0

[题解]

        对于这道题,我们可以很容易的写出方程:f[i]=max(f[j]+a*(s[i]-s[j])^2+b*(s[i]-s[j])+c);因为数据范围是100W,所以我们猜测这个dp要用斜率优化或单调队列优化.

        现在我们对他做一下变形.

        f[i]=max(f[j]+a*(s[i]*s[i]+s[j]*s[j]+2*s[i]*s[j])+b*(s[i]-s[j])+c)
            =max(f[j]+a*a[j]*a[j]+2*a*s[i]*s[j]-b*s[j])+a*s[i]*s[i]+b*s[i]+c

        可以发现,f[j]+a*a[j]*a[j]-b*s[j]只与j有关,a*s[i]*s[i]+b*s[i]+c只与i有关,2*a*s[i]*s[j]与i,j有关且单调递减(a<0),而f[j]+a*a[j]*a[j]-b*s[j]则没有单调性.

        我们令k=a*s[i]*s[i]+b*s[i]+c,x[i]=2*a*s[i],y[i]=f[i]+a*a[i]*a[i]-b*s[i],则:f[i]=max(y[i]+s[i]*x[i])+k

        令P=y[j]+s[i]*x[j],我们的目标就是最大化P.移项得:y[j]=P-s[i]*x[j].

       我们再令x[j]=-x[j],则:y[j]=s[i]*x[j]+P.其中,x随j单调递增.由于s随i单调递增,所以直线的斜率也单调递增,所以我们可以利用斜率优化来解决这道题.

Code:

program commando;
type int=longint;real=extended;
var
        i,j,m,l,r,n:int;
        a,b,k,c:real;
        x,y,f,s:array[0..1000000]of real;
        q:array[0..1000000]of int;

begin
        assign(input,'commando.in');reset(input);
        assign(output,'commando.out');rewrite(output);
        read(n);
        read(a,b,c);s[0]:=0;
        for i:=1 to n do begin
                read(s[i]);s[i]:=s[i-1]+s[i];
        end;
        l:=1;r:=1;q[l]:=0;f[0]:=0;
        for i:=1 to n do begin
                k:=c+b*s[i]+a*s[i]*s[i];
                while(l<r)and((y[q[l]]-y[q[l+1]])/(x[q[l]]-x[q[l+1]])<s[i])do inc(l);
                f[i]:=k+y[q[l]]-s[i]*x[q[l]];
                x[i]:=2*a*s[i];y[i]:=f[i]-b*s[i]+a*s[i]*s[i];
                while(l<r)and((y[q[r]]-y[q[r-1]])/(x[q[r]]-x[q[r-1]])>(y[q[r]]-y[i])/(x[q[r]]-x[i]))do dec(r);
                inc(r);q[r]:=i;
        end;
        write(f[n]:0:0);
        close(input);close(output);
end.

另外,我想申明一下,由于本人写blog的主要目的是将刚学过的东西巩固一下,所以代码的效率不一定有多高,实现方式不一定很精简,请某些同学就不要挑一些小毛病了.贴上来的程序只是做一个参考,不过我还是会保证正确性的.


BY QW

转载请注明出处

源码地址: https://pan.quark.cn/s/a4b39357ea24 遗传算法 - 简书 遗传算法的理论是根据达尔文进化论而设计出来的算法: 人类是朝着好的方向(最优解)进化,进化过程中,会自动选择优良基因,淘汰劣等基因。 遗传算法(英语:genetic algorithm (GA) )是计算数学中用于解决最佳化的搜索算法,是进化算法的一种。 进化算法最初是借鉴了进化生物学中的一些现象而发展起来的,这些现象包括遗传、突变、自然选择、杂交等。 搜索算法的共同特征为: 首先组成一组候选解 依据某些适应性条件测算这些候选解的适应度 根据适应度保留某些候选解,放弃其他候选解 对保留的候选解进行某些操作,生成新的候选解 遗传算法流程 遗传算法的一般步骤 my_fitness函数 评估每条染色体所对应个体的适应度 升序排列适应度评估值,选出 前 parent_number 个 个体作为 待选 parent 种群(适应度函数的值越小越好) 从 待选 parent 种群 中随机选择 2 个个体作为父方和母方。 抽取父母双方的染色体,进行交叉,产生 2 个子代。 (交叉概率) 对子代(parent + 生成的 child)的染色体进行变异。 (变异概率) 重复3,4,5步骤,直到新种群(parentnumber + childnumber)的产生。 循环以上步骤直至找到满意的解。 名词解释 交叉概率:两个个体进行交配的概率。 例如,交配概率为0.8,则80%的“夫妻”会生育后代。 变异概率:所有的基因中发生变异的占总体的比例。 GA函数 适应度函数 适应度函数由解决的问题决定。 举一个平方和的例子。 简单的平方和问题 求函数的最小值,其中每个变量的取值区间都是 [-1, ...
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值