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


    题意:

    有 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;
    }
  • 相关阅读:
    线程锁(互斥锁Mutex)及递归锁
    threading模块,python下的多线程
    笔试面试题实现
    Socket编程,SocketServer模块
    iOS开发- 文件共享(利用iTunes导入文件, 并且显示已有文件)
    iOS 根据文件名获取到文件路径
    IOS UILabel自动换行
    🐤小记
    iOS 获取当前月份的天数(转)、
    IOS 在Ipad 横屏 上使用UIImagePickerController
  • 原文地址:https://www.cnblogs.com/kedebug/p/2942590.html
Copyright © 2020-2023  润新知