信息学奥赛一本通 1613:打印文章

【题目链接】

ybt 1613:打印文章

【题目考点】

1. 斜率优化动规

斜率优化动规相关知识见:信息学奥赛一本通 1607:【 例 2】任务安排 2 | 洛谷 P10979 任务安排 2

【解题思路】

每个单词可以当做一个整数,这是个整数序列。
c i c_i ci为第 i i i个整数,设 c c c序列的前缀和 s s s, s i s_i si表示前 i i i个整数的加和。 m m m为题目中的 M M M。

1. 状态定义

  • 阶段:前 i i i个数
  • 决策:一个数属于哪个子段
  • 策略:子段划分的方案
  • 策略集合:前 i i i个数的所有子段划分方案
  • 条件:代价最小
  • 统计量:代价

状态定义 d p i dp_i dpi:前 i i i个数的所有子段划分方案中,代价最小的方案的代价。

初始状态 d p 0 = 0 dp_0=0 dp0=0

2. 状态转移方程

  • 策略集合:前 i i i个数的所有子段划分方案
  • 分割策略集合:根据分出的最后一个子段的长度分割策略集合

设最后一个子段为区间 j + 1 , i j+1,i j+1,i, j j j最小可以为0,最大为 i − 1 i-1 i−1,所以 0 ≤ j ≤ i − 1 0\le j \le i-1 0≤j≤i−1。

该子段的代价为 ( ∑ x = j + 1 i c x ) 2 + m = ( s i − s j ) 2 + m (\sum\limits_{x=j+1}^ic_x)^2+m=(s_i-s_j)^2+m (x=j+1∑icx)2+m=(si−sj)2+m

前 i i i个数进行子段划分的最小代价,为前 j j j个数进行子段划分的最小代价,再加上子段 j + 1 , i j+1,i j+1,i的代价,为 d p j + ( s i − s j ) 2 + m dp_j+(s_i-s_j)^2+m dpj+(si−sj)2+m,对所有可能的 j j j的取值,取该表达式的最小值。

因此状态转移方程为: d p i = min ⁡ { d p j + ( s i − s j ) 2 + m } , 0 ≤ j ≤ i − 1 dp_i=\min\{dp_j+(s_i-s_j)^2+m\},0\le j\le i-1 dpi=min{dpj+(si−sj)2+m},0≤j≤i−1。

该状态转移方程可以使用斜率优化动规。

去掉min,将与 j j j相关的量当做变量,整理方程
d p i = d p j + ( s i − s j ) 2 + m = d p j + s i 2 − 2 s i s j + s j 2 + m dp_i = dp_j+(s_i-s_j)^2+m=dp_j+s_i^2-2s_is_j+s_j^2+m dpi=dpj+(si−sj)2+m=dpj+si2−2sisj+sj2+m
d p j + s j 2 = 2 s i s j + d p i − s i 2 − m dp_j+s_j^2=2s_is_j+dp_i-s_i^2-m dpj+sj2=2sisj+dpi−si2−m

设 y = d p j + s j 2 , x = s j , k = 2 s i , b = d p i − s i 2 − m y=dp_j+s_j^2, x = s_j, k = 2s_i, b = dp_i-s_i^2-m y=dpj+sj2,x=sj,k=2si,b=dpi−si2−m

则该方程就是直线方程 y = k x + b y=kx+b y=kx+b,决策点为 ( s j , d p j + s j 2 ) (s_j, dp_j+s_j^2) (sj,dpj+sj2),看直线经过哪个决策点时截距 b b b最小,将决策点的值带入,即可求出 d p i dp_i dpi。

已知 c i c_i ci是非负的,所以随着 i i i的增大, s i s_i si增大,斜率 k k k随之增大。可以进行队头出队操作,取队头即为最优决策点。

最终结果为 d p n dp_n dpn

【题解代码】

解法1:斜率优化动规

cpp 复制代码
//j+1~i为最后一段 
//dp[i] = min{dp[j]+(s[i]-s[j])^2+M}, 0<=j<=i-1 
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 500005;
LL n, m, a[N], s[N], dp[N];//dp[i]:前i个数的所有划分中,代价最小的划分方案的代价 
int q[N], l, r;
LL X(int j)
{
	return s[j];
}
LL Y(int j)
{
	return dp[j]+s[j]*s[j];
}
LL K(int i)
{
	return 2*s[i];
}
bool cmp(LL a1, LL b1, LL a2, LL b2)//a1/b1 <= a2/b2
{
	return a1*b2 <= a2*b1;
}
int main()
{
	ios::sync_with_stdio(false);
	cin.tie(nullptr);
	while(cin >> n >> m)
	{
		l = 1, r = 0;//单调队列清空 
		for(int i = 1; i <= n; ++i)
		{
			cin >> a[i];
			s[i] = s[i-1]+a[i];
		}
		q[++r] = 0;
		for(int i = 1; i <= n; ++i)
		{
			while(l < r && cmp(Y(i-1)-Y(q[r]), X(i-1)-X(q[r]), Y(q[r])-Y(q[r-1]), X(q[r])-X(q[r-1])))
				--r;
			q[++r] = i-1;
			while(l < r && cmp(Y(q[l+1])-Y(q[l]), X(q[l+1])-X(q[l]), K(i), 1))
				++l;
			dp[i] = dp[q[l]]+(s[i]-s[q[l]])*(s[i]-s[q[l]])+m;
		}
		cout << dp[n] << '\n';
	}
	return 0;
}
相关推荐
MicroTech20258 分钟前
量子隐形传态路线的瓶颈与突破,微算法科技(MLGO)以技术创新助力量子通信长距离组网
科技·算法·量子计算
洛水水8 分钟前
【力扣100题】89.下一个排列
数据结构·算法·leetcode
洛水水9 分钟前
【力扣100题】90.寻找重复数
算法·leetcode·职场和发展
鱼子星_15 分钟前
【数据结构】排序的拓展——快速排序的生态多样性与归并排序沾染文件操作
c语言·数据结构·算法
alphaTao15 分钟前
LeetCode 每日一题 2026/6/8-2026/6/14
算法·leetcode
KaMeidebaby20 分钟前
卡梅德生物技术快报|噬菌体展示文库构建全流程解析 | 大豆球蛋白纳米抗体筛选实践
人工智能·python·tcp/ip·算法·机器学习
CC数学建模27 分钟前
2026年第十六届APMCM 亚太地区大学生数学建模竞赛(中文赛项)赛题B题:高性能芯片热管理系统的优化问题完整思路、代码、模型、文章,全网首发高质量分享!
python·算法·数学建模
爱睡懒觉的焦糖玛奇朵36 分钟前
【视觉检测之人员奔跑检测算法开发思路】
人工智能·python·深度学习·算法·yolo·视觉检测
05候补工程师41 分钟前
【408考研复习】数据结构核心笔记:字符串模式匹配与内部排序算法全解析
数据结构·经验分享·笔记·考研·算法·排序算法
kyle~41 分钟前
机器人日志系统
c++·单片机·嵌入式硬件·机器人·ros2