HDOJ 3507 Print Article(DP + 斜率优化)

本文介绍了一种解决特定打印费用优化问题的算法。通过动态规划和斜率优化技术,实现了从N个单词中选择K个进行打印,使得总的打印费用最小化的高效算法。详细解释了转移方程的构建、斜率优化的原理及其在实际应用中的具体实现步骤。

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

题意:

有 N 个单词,打印第 i 个单词需要 Ci 的费用,并且 K 个单词在一行打印时会产生一个费用和。求最小总费用。

思路:

1. 转移方程为:dp[i] = dp[j] + cost[j+1, i]; 其中 j ∈ [0, i), cost[j+1, i] = (C[i] - C[j])+ M;

2. 常规方法枚举的话,时间复杂度为 O(N2); 想办法对 cost 展开利用斜率优化降低时间复杂度。

3. dp[i] = dp[j] + Cj- 2 * Ci * Cj + Ci2 +M; -> Y = dp[j] + Cj2, X = Cj, a = 2 * Ci(递增);利用下凸函数特性以及队列解题。

4. 题目中有个特殊的地方也需要考虑:当某个单词打印费用为 0 时,Ci = Cj -> dp[i] = dp[j]; 去除重复元素即可。

 

#include <iostream>
#include <algorithm>
using namespace std;

const int MAXN = 500010;

long long int dp[MAXN], C[MAXN];
int deq[MAXN];

inline double slope(int i, int j)
{
    return (double)(dp[i] + C[i] * C[i] - dp[j] - C[j] * C[j]) / (C[i] - C[j]);
}

int main()
{
    int N, M;
    while (scanf("%d %d", &N, &M) != EOF)
    {
        C[0] = 0;
        for (int i = 1; i <= N; ++i)
            scanf("%lld", &C[i]), C[i] += C[i-1];

        int s = 0, e = 0;
        for (s = 1, e = 1; e <= N; ++e)
            if (C[s] != C[e])
                C[++s] = C[e];

        N = s;

        s = e = 0;
        dp[0] = deq[s] = 0;

        for (int i = 1; i <= N; ++i)
        {
            while (s < e && slope(deq[s+1], deq[s]) <= (double)(2 * C[i]))
                ++s;

            int j = deq[s];
            dp[i] = dp[j] + (C[i] - C[j]) * (C[i] - C[j]) + M;

            while (s < e && slope(deq[e], deq[e-1]) >= slope(i, deq[e]))
                --e;
            deq[++e] = i;
        }
        printf("%lld\n", dp[N]);
    }
    return 0;
}

转载于:https://www.cnblogs.com/kedebug/archive/2013/03/04/2942590.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值