P1052 过河
知识点: DP
原题面
题意简述
给定一数轴,标号 \(0\sim L\)。
从 \(0\) 出发,每次可向右移动 \(S\sim T\) 个单位。
数轴上有 \(M\) 个点,求移动到数轴外,经过的最少的点数。
\(1\le M\le 100,\ 1 \le L\le 10^9, 1\le S\le T\le 10\)。
分析题意
算法一
我会暴力!
设 \(f_i\) 表示,到达 \(i\) 时,经过的最少的点数。
令 \(a_i\) 表示位置为 \(i\) 的点的数量,则有:
\(S,T\) 较小,可看做常数,复杂度 \(O(L)\) 级别。
期望得分 \(30\text{pts}\)。
算法二
发现 \(M \le 100\),但 \(L\le 10^9\)。
数轴上有大段的空白区域没有点存在,这些位置对答案无贡献。
而算法一中仍然在这些位置进行了转移,浪费了大量时间。
当 \(S < T\) 时:
发现有很多移动距离,都可以凑出来。
这个问题类似 Noip2017 D1T1 小凯的疑惑。
如 \(S=5, T=6\) 时,最大的凑不出来的距离为 \(19\),比 \(19\) 更大的距离均可凑出来。
考虑两个距离过大的点。
显然,从左边的点出发,最大的凑不出来的距离 右侧的位置(包括右侧的点),均可通过凑距离到达。
而两个点之间的位置 对答案无贡献。
在不影响 可到达性的同时,可考虑将两点距离缩小。
缩小到仍出现 上述任意点可到达的情况,不影响答案。
以下有两种缩法:
- \(2520\) 缩,由于 \(\operatorname{lcm}(1\sim 10) = 2520\),距离为 \(2520\) 时,必然出现上述情况。
- \(71\) 缩, \(9,10\) 凑不出来的最大距离为 \(9 \times 10 - 9 - 10 = 71\),则距离 \(71\) 是出现上述情况的最小值。
题解中神仙们给了缩距离的详细证明 Luogu题解。
复杂度 \(O(kM)\) (\(k\) 为缩成的距离),期望得分 \(100\text{pts}\)。
WA 成 80 了。
发现算法二并不适用于 \(S=T\) 的情况。
\(S=T\) 时,移动路径已知,先后经过 \(S,2S,...,kS\) 这些点。
则 位置为 \(S\) 的倍数的点的数量 即为答案。
代码实现
写的时候根本没考虑应该缩成什么距离= =
想着大就完事了,直接缩成 10000 了。
//知识点:DP
/*
By:Luckyblock
*/
#include <cstdio>
#include <ctype.h>
#include <cstring>
#include <algorithm>
#define ll long long
const int kMaxm = 110;
const int kMaxDis = 10000;
const int kMaxn = 110 * kMaxDis;
//=============================================================
int L, S, T, M, pos[kMaxm];
int a[kMaxn], f[kMaxn];
//=============================================================
inline int read() {
int f = 1, w = 0; char ch = getchar();
for (; !isdigit(ch); ch = getchar()) if (ch == '-') f = -1;
for (; isdigit(ch); ch = getchar()) w = (w << 3) + (w << 1) + (ch ^ '0');
return f * w;
}
//=============================================================
int main() {
L = read(), S = read(), T = read(), M = read();
for (int i = 1; i <= M; ++ i) pos[i] = read();
std :: sort(pos + 1, pos + M + 1);
if (S == T) {
int ans = 0;
for (int i = 1; i <= M; ++ i ) ans += pos[i] % S == 0;
printf("%d\n", ans);
return 0;
}
L = 0;
for (int i = 1; i <= M; ++ i) {
int dis = pos[i] - pos[i - 1];
if (pos[i] - pos[i - 1] > kMaxDis) dis = kMaxDis;
a[(L = L + dis)] ++;
}
L += kMaxDis;
memset(f, 63, sizeof(f));
f[0] = 0;
for (int i = 1; i <= L; ++ i) {
for (int j = std :: max(i - T, 0); j <= i - S; ++ j) {
f[i] = std :: min(f[i], f[j] + a[i]);
}
}
printf("%d\n", f[L]);
return 0;
}
原文地址:https://www.cnblogs.com/luckyblock/p/13286984.html
- 常用业务接口界面化 in python flask
- 打印机设置(PrintDialog)、页面设置(PageSetupDialog) 及 RDLC报表如何选择指定打印机
- 区块链推动支付革命
- MySQL常见的库操作,表操作,数据操作集锦及一些注意事项
- nohup命令
- 跨浏览器的剪贴板访问解决方案
- 装逼必备:大型分布式网站术语分析
- 年前爆炸一波!小程序视频功能来了!
- ubuntu13.04环境hadoop1.2.1单机模式安装
- silverlight:telerik RadControls中RadGridView的一个Bug及解决办法
- scope引起的问题
- JS正则表达式常用函数汇总
- 修改(同步)linux时间
- “爬虫”程序吃掉低价机票 高科技“黄牛”怎么破?
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 企业远程办公视频会议系统EasyRTC-SFU下侧边栏边框超限问题如何解决?
- 编写高质量可维护的代码:数据建模
- 新版企业远程办公视频通话系统EasyRTC-SFU,如何解决用户登录信息更新不及时的问题?
- 服务应用突然宕机了?别怕,Dubbo 帮你自动搞定服务隔离!
- 33.Python字符串方法find以及与序列解包的技巧结合
- 代码审计从0到1 —— Centreon One-click To RCE
- 一文带你深扒ClassLoader内核,揭开它的神秘面纱!
- 小知识:OGG的TRANLOGOPTIONS MINEFROMACTIVEDG参数
- oracle转postgreSQL修改点
- 重学数据结构(三、队列)
- Jmeter系列(68)- BeanShell 内置变量 prev
- 聊聊java中的哪些Map:(六)ConcurrentHashMap源码分析
- 任意文件包含漏洞的绕过方式
- XXE实体注入漏洞详解
- ent orm笔记2---schema使用(下)