乘电梯(动规+单调队列队头优化)
题目描述
【输入文件】
第一行是电梯的数量和大楼层数。然后每行是一个电梯服务的最低层和最高层。
最多有200个电梯,大楼不超过10000层。
显然问题是有解的。不然你是怎么上去的呢?
【输出文件】
最短时间。精确到5位小数。
输入
输出
样例输入
6 15 4 8 10 14 1 5 7 11 13 15 1 13
样例输出
20.32308
题解
在某不知名的菜oj上我目前是rank1(当然不知道以后怎样哈哈哈,我完全没加快速io,毕竟也没什么卵用)
第一个想法是O(n * m * m)的动规,很容易想到,n是电梯数,m是大楼层数
但是显然不行
反过来看看我们的做法
我们是从上到下枚举,每次枚一个电梯就需要枚该层以上所有的值求最小
发现确定了特定层对应特定电梯时,这个值是只和这个当前状态有关的,和之后递推的状态无关
所以可以在求到每一层的最小后,更新从这层开始能坐的电梯的最小值,枚举到下一层能坐这个电梯时,就可以直接用这个值,还是很好想的
可以类比一下01背包的优化,是取单调队列的队头的思想
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | #include <stdio.h> #include <string.h> #include <iostream> const double oo = 0x3f3f3f3f; using namespace std; inline void read( int &x) { int c = getchar (); while (c < '0' || c > '9' ) c = getchar (); while (c >= '0' && c <= '9' ) x = x * 10 + c - 48, c = getchar (); } double f[10001], cur[201]; int n, m, l[201], r[201]; inline double calc( double a, double b) { return (a*(a + 1) + b*(b + 1)) / 2 / (a + b + 1);} int main() { read(n), read(m); for ( int i = 1; i <= n; ++i) read(l[i]), read(r[i]); fill(cur + 1, cur + 1 + n, oo); for ( int i = 1; i <= n; ++i) if (r[i] == m) cur[i] = calc(m - l[i], 0); for ( int j = m - 1; j >= 1; --j) { f[j] = oo; for ( int i = 1; i <= n; ++i) if (l[i] <= j && j <= r[i]) f[j] = min(f[j], cur[i]); for ( int i = 1; i <= n; ++i) if (l[i] <= j && j <= r[i]) cur[i] = min(cur[i], f[j] + calc(r[i] - j, j - l[i])); } printf ( "%.5lf\n" , f[1] + m - 1); return 0; } |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· 写一个简单的SQL生成工具
· AI 智能体引爆开源社区「GitHub 热点速览」
· C#/.NET/.NET Core技术前沿周刊 | 第 29 期(2025年3.1-3.9)