GYM100524 E

题意:
在数轴上有n个村子感染了ebola,你要去治疗他们。具体来说,一开始你在1号村子。每天,如果你在村子x,你可以选择治疗村子x的人,或移动到x-1或x+1。每天结束时,如果村子i没有被治疗过,这个村会有ai人死亡。特别的,如果某天你选择了跨过一个没治疗的村子,那你下一次回头时一定要回来治疗这个村子。就是
这里写图片描述
去的时候治疗了2和4,那第一次回头后,在治疗1和3前不能再回头。
问最少死亡人数。
n<=3000
ai<=10^9

#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<cmath>
#include<iostream>
#define LL long long
#define N 3100
using namespace std;
LL a[N],s[N],f[N],inf;
int n;
int main()
{
    freopen("ebola.in","r",stdin);
    freopen("ebola.out","w",stdout);
    while(1)
    {
        scanf("%d",&n);
        if(n==0) break;
        inf=0;
        for(int i=1;i<=n;i++) scanf("%lld",&a[i]),inf+=a[i]*(i-1+i-1);
        for(int i=1;i<=n;i++) f[i]=inf,s[i]=s[i-1]+a[i];
        for(int r=1;r<=n;r++)
        {
            LL tmp=0;
            for(int l=r;l>=1;l--)
            {
                tmp+=min(1ll*l*a[l]+s[r]-s[l],3ll*r*a[l]-2ll*l*a[l]);
                LL t=3*(r-l)+r-l+1,p=tmp-(s[r]-s[l-1])*l;
                if(l>1) t++,p+=s[r]-s[l-1];
                f[r]=min(f[r],f[l-1]+p+(s[n]-s[r])*t);
            }
        }
        printf("%lld\n",f[n]);
    }
    return 0;
}

题解:
答案一定是长这个样子的
这里写图片描述
我们只要能算出每段的最优代价就行了
对于一段[l,r],他对r后面的部分影响是固定的,直接计算
现在就是要决策对于l,r之间的所有点,他是去的时候治疗还是回的时候治疗
重要的一个性质就是对于i< j,无论j怎么决策,如果i是去时治疗,那就一定会在j之前被治疗;如果是回时治疗,就一定在j之后被治疗。这样就可以用贡献和自身代价表示出花费了。
具体就是,
=(il)ai+srsi
=(3r2il)ai
注意两边都是lai,即决策与l无关。所以枚举右端点O(n2)dp一遍就好。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值