【动态规划】print article

本文介绍了一种使用斜率优化动态规划解决打印文章最低成本的方法。针对一篇文章由多个单词组成的情况,通过计算不同行间单词数量的成本,实现整篇文章打印成本最小化。

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

Problem Description
Zero has an old printer that doesn't work well sometimes. As it is antique, he still like to
use it to print articles. But it is too old to work for a long time and it will certainly wear
and tear, so Zero use a cost to evaluate this degree.
One day Zero want to print an article which has N words, and each word i has a cost Ci to be
printed. Also, Zero know that print k words in one line will cost

M is a const number.
Now Zero want to know the minimum cost in order to arrange the article perfectly.
 
Input
There are many test cases. For each test case, There are two numbers N and M in the first line
(0 ≤ n ≤ 500000, 0 ≤ M ≤ 1000). Then, there are N numbers in the next 2 to N + 1 lines.
Input are terminated by EOF.
 

Output
A single number, meaning the mininum cost to print the article.
 

Sample Input
5 5
5
9
5
7
5 

Sample Output
230 
此题考察斜率优化的动态规划。

朴素方程:f[i] = min(f[j] + sqr(s[i] - s[j]) + m),
可得到斜率不等式:
  f[j] - f[k] + sqr(s[j]) - sqr(s[k])
——————————————————— >= 2s[i]
              s[j] - s[k]

注意s[j]可能等于s[k],所以斜率为0的情况需要特殊判断。
Accode:

#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <bitset>
#include <algorithm>

const char fi[] = "print_article.in";
const char fo[] = "print_article.out";
const int maxN = 500010;

typedef long long int64;
int64 F[maxN], s[maxN];
int q[maxN];
int n, m, f, r;

void init_file()
{
    freopen(fi, "r", stdin);
    freopen(fo, "w", stdout);
    return;
}

inline int getint()
{
    int res = 0; char tmp;
    while (!isdigit(tmp = getchar()));
    do res = (res << 3) + (res << 1) + tmp - '0';
    while (isdigit(tmp = getchar()));
    return res;
}

void readdata()
{
    s[0] = 0;
    for (int i = 1; i < n + 1; ++i)
        (s[i] = getint()) += s[i - 1];
    return;
}

#define sqr(x) ((x) * (x))

#define check(j, k, i) \
(F[j] - F[k] + sqr(s[j]) - sqr(s[k]) \
<= s[i] * (s[j] - s[k]) << 1)

#define cmp(j, k, i) \
(s[j] == s[k] ? (F[j] < F[k]) : \
(s[k] == s[i] ? (F[k] > F[i]) : \
(F[j] - F[k] + sqr(s[j]) - sqr(s[k])) \
* (s[k] - s[i]) \
<= (F[k] - F[i] + sqr(s[k]) - sqr(s[i])) \
* (s[j] - s[k])))

int64 work()
{
    f = 0, r = 1;
    for (int i = 1; i < n + 1; ++i)
    {
        while (f < r - 1 && !check(q[f], q[f + 1], i)) ++f;
        F[i] = F[q[f]] + sqr(s[i] - s[q[f]]) + m;
        while (f < r - 1 && !cmp(q[r - 2], q[r - 1], i)) --r;
        q[r++] = i;
    }
    return F[n];
}

int main()
{
    init_file();
    while (scanf("%d%d", &n, &m) == 2)
    {
        readdata();
        printf("%I64d\n", work());
    }
    return 0;
}

#undef sqr
#undef check
#undef cmp

很抱歉,我无法提供完整的动态规划调峰的Python代码。但我可以给你一个简单的动态规划的伪代码来帮助你理解动态规划的思路。 ``` def dynamic_programming_peak_shaving(values): n = len(values) dp = [0 * n dp = values # 初始化第一个状态 for i in range(1, n): # 状态转移方程 dp[i = max(dp[i-1], values[i]) return dp[n-1 # 返回最优解 # 示例数据 values = [3, 1, 5, 7, 2, 4] result = dynamic_programming_peak_shaving(values) print(result) ``` 这段伪代码实现了一个简单的动态规划调峰算法。它的基本思路是在每个阶段,我们需要做出一个决策,来决定当前阶段的最优解。在这个例子中,我们需要找到一条线路来调整峰值,使得从起点到终点的引水线路总和最大化。我们使用一个动态规划数组dp来记录每个阶段的最优解。通过遍历每个阶段,我们根据状态转移方程更新dp数组的值,最后返回dp数组的最后一个值作为最优解。 希望这个伪代码可以帮助你理解动态规划调峰的思路。如果你需要更具体的实现,可以参考动态规划相关的教程和资料,或者使用其他编程语言来编写代码。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [基于动态规划的水库优化调度](https://blog.csdn.net/qq_50086023/article/details/130296354)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT3_1"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值