洛谷P4544 [USACO10NOV] Buying Feed G 题解 单调队列优化DP

news/2024/9/21 2:01:39

题目链接:https://www.luogu.com.cn/problem/P4544

解题思路:

首先我们可以将 \(N\) 家商店按照坐标 \(X_i\) 从小到大排序(可能会有一些商店坐标相同的情况,但是不影响)。

并且我们可以将家看做第 \(N+1\) 个商店(当然,\(F_{N+1} = 0\))。

定义状态 \(F_{i,j}\) 表示在前 \(i\) 家商店买了恰好 \(j\) 吨饲料的总花费。

则状态转移方程为:

\[f_{i,j} = \min\limits_{0 \le k \le \min(j, F_i)} f_{i-1, j-k} + (X_i - X_{i-1}) \times (j-k)^2 + C_i \times k \]

示例程序:

#include <bits/stdc++.h>
using namespace std;
const int maxn = 505, maxk = 1e4 + 5;
long long f[maxn][maxk];
int K, E, n;
struct Node {int x, f, c;
} a[maxn];int main() {scanf("%d%d%d", &K, &E, &n);for (int i = 1; i <= n; i++)scanf("%d%d%d", &a[i].x, &a[i].f, &a[i].c);sort(a+1, a+n+1, [](Node a, Node b){return a.x < b.x;});a[n+1] = {E, 0, 0};memset(f, 0x3f, sizeof f);f[0][0] = 0;for (int i = 1, F = 0; i <= n+1; i++) {F = min(K, F + a[i].f);for (int j = 0; j <= F; j++) {for (int k = 0; k <= min(j, a[i].f); k++) {f[i][j] = min(f[i][j], f[i-1][j-k] + (long long)(a[i].x-a[i-1].x)*(j-k)*(j-k) + (long long)a[i].c * k);}}}printf("%lld\n", f[n+1][K]);return 0;
}

但是算法的时间复杂度为 \(O(N \times K^2)\),会超时。(数据水了点, TLE 了一组,拿了 95 分)

接下来考虑如何优化。

考试将 \(j-k\) 替换为 \(k\),上式变为:

\[f_{i,j} = \min\limits_{max(0, j-F_i) \le k \le j} f_{i-1,k} + (X_i - X_{i-1}) \cdot k^2 + C_i \cdot (j - k) \]

其中,\(C_i \cdot j\) 是一个固定项(和 \(k\) 无关,可以提出来)

然后定义

\[g(i, k) = f_{i-1,k} + (X_i - X_{i-1}) \cdot k^2 - C_i \cdot k \]

\(f_{i,j} = C_i \cdot j + \min\limits_{max(0, j-F_i) \le k \le j} g(i, k)\)

然后可以发现,随着 \(j\) 的增大,\(k\) 的左边界(\(max(0, j-F_i)\))是逐渐变大的,\(k\) 右边界(\(j\))也是逐渐变大的,所以我们可以用 单调队列 维护这个区间(任意时刻单调队列的队首对应的就是 \(\min\limits_{max(0, j-F_i) \le k \le j} g(i, k)\))。

使用单调队列优化后,算法的时间复杂度就变为了 \(O(NK)\)(状态数 \(O(NK)\),状态转移 \(O(1)\))。

示例程序:

#include <bits/stdc++.h>
using namespace std;
const int maxn = 505, maxk = 1e4 + 5;
long long f[maxn][maxk];
int K, E, n;
struct Node {int x, f, c;
} a[maxn];long long g(int i, int k) {return f[i-1][k] + (long long) (a[i].x - a[i-1].x) * k * k - (long long) a[i].c * k;
}int main() {scanf("%d%d%d", &K, &E, &n);for (int i = 1; i <= n; i++)scanf("%d%d%d", &a[i].x, &a[i].f, &a[i].c);sort(a+1, a+n+1, [](Node a, Node b){return a.x < b.x;});a[n+1] = {E, 0, 0};fill(f[0], f[0] + maxn*maxk, (long long)1e18);f[0][0] = 0;for (int i = 1, F = 0; i <= n+1; i++) {F = min(K, F + a[i].f);deque<int> que;for (int j = 0; j <= F; j++) {while (!que.empty() && que.front() < j - a[i].f)que.pop_front();while (!que.empty() && g(i, que.back()) >= g(i, j))que.pop_back();que.push_back(j);f[i][j] = (long long) a[i].c * j + g(i, que.front());}}printf("%lld\n", f[n+1][K]);return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.ryyt.cn/news/62792.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈,一经查实,立即删除!

相关文章

游戏技术

目录显示相关的术语每个帧的像素:分辨率多个帧的刷新:刷新率、帧率每个像素的颜色编码码率显卡渲染技术DLSS2 牺牲画质 提高帧率DLSS3 进一步提高帧率 刷新更流畅 显示相关的术语 每个帧的像素:分辨率 分辨率 = 水平宽度的像素数(列数) x 垂直高度的像素数(行数)速记 分辨率…

基于双闭环PI的SMO无速度控制系统simulink建模与仿真

1.课题概述基于双闭环PI的SMO无速度控制系统simulink建模与仿真,基于双闭环PI的SMO无速度控制系统主要由两个闭环组成:一个是电流环,另一个是速度环。电流环作为内环,主要负责电流的快速跟踪控制;速度环作为外环,负责速度的精确控制。这种双闭环结构可以有效提高系统的动…

基于ACO蚁群优化的UAV最优巡检路线规划算法matlab仿真

1.程序功能描述 基于ACO蚁群优化法的UAV最优巡检路线规划。蚁群优化算法源于对自然界蚂蚁寻找食物路径行为的模拟。在无人机巡检路线规划问题中,无人机被认为是“蚂蚁”,巡检点视为“食物源”,目标是找到一条总距离(或总能耗、总时间等)最短的巡检路线。 2.测试软件…

痞子衡嵌入式:如果i.MXRT离线无法启动,试着分析ROM启动日志

大家好,我是痞子衡,是正经搞技术的痞子。今天痞子衡给大家介绍的是恩智浦i.MXRT系列MCU的ROM启动日志。关于 i.MX RT 启动问题解决的文章,痞子衡写过非常多,其中大部分都是具体到某一类启动设备下的具体问题分析,比较依赖经验,这些经验当然是非常有用的。此外也有一篇 《…

基于A律压缩的PCM脉冲编码调制通信系统simulink建模与仿真

1.算法运行效果图预览 (完整程序运行后无水印) 2.算法运行软件版本 matlab2022a3.部分核心程序 (完整版代码包含详细中文注释和操作步骤视频)4.算法理论概述脉冲编码调制(Pulse Code Modulation, PCM)是一种将模拟信号转换为数字信号的通信技术,广泛应用于电话通信、音频…

室内导航的界面该如何设计

室内导航的界面该如何设计?发点例子你看看

【笔记】机器学习算法在异常网络流量监测中的应用

这段时间在找方向,又看不懂文章,只能先从一些相对简单的综述类看起,顺便学学怎么写摘要相关工作的。机器学习算法在异常网络流量监测中的应用 原文:Detecting Network Anomalies in NetFlow Traffic with Machine Learning Algorithms 原文链接:Detecting Network Anomali…