【BZOJ 1010】玩具装箱

本文介绍了一种结合动态规划与单调队列优化的方法,用于解决特定类型的最优化问题。通过状态定义、状态转移方程推导及代码实现,详细展示了如何利用单调队列优化动态规划中的计算过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

思路:

f[i]表示1i号物品的最小代价,s[i]c[i]的前缀和。
状态转移方程:f[i]=min{f[j]+(s[i]s[j]+ij1L)2}
考虑对方程进行优化。
t[i]=s[i]+i,则f[i]=min{f[j]+(t[i]t[j]1L)2}
由于c[i]非负,所以s[i]i增长时单调不减。
m=t[i]1L,则f[i]=min{f[j]+(mt[j])2}
ip,q,两个可能的j的取值的地方转移,不妨令p<q
若方案q优于p,则有:f[p]+(mt[p])2>f[q]+(mt[q])2
展开:f[p]2m×t[p]+t[p]2>f[q]2m×t[q]+t[q]2
整理:

(f[q]+t[q]2)(f[p]+t[p]2)2×(t[q]t[p])<m

因为i增加的的时候,m是单调不降的,所以可以用单调队列维护。

代码:

#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
typedef long long ll;
const int maxn = 50010;
int n, L;
ll c[maxn], f[maxn], s[maxn], q[maxn], t[maxn], l, r;
ll sqr(ll x){return x*x;}
double slope(ll p, ll q){
    return ((f[q]+sqr(t[q]))-(f[p]+sqr(t[p])))/(2.0*(t[q]-t[p]));
}
int main(){
    scanf("%d%d", &n, &L);
    for(int i = 1; i <= n; i ++){
        scanf("%lld", &c[i]);
        s[i] += s[i-1]+c[i];
        t[i] = s[i] + i;
    }
    l = 1, r = 1;
    for(int i = 1; i <= n; i ++){
        while(l<r && slope(q[l], q[l+1]) < t[i]-L-1) l ++;
        f[i] = f[q[l]] + sqr(t[i]-t[q[l]]-L-1);
        while(l<r && slope(q[r-1], q[r]) > slope(q[r], i)) r --;
        q[++ r] = i;
    }
    printf("%lld", f[n]);
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值