题目描述
起点与终点相隔 4500 米。现 Charley 需要从起点骑车到终点。但是,他有个习惯,沿途需要有人陪伴,即以相同的速度, 与另外一个人一起骑。而当他遇到以更快的速度骑车的人时,他会以相应的速度跟上这个更快的人。先给定所有与 Charley 同路的人各自的速度与出发时间,问 Charley 以这种方式跟人,骑完 4500 米需要多少时间。得出的结果若是小数,则向上取整。
输入输出格式
输入格式
输入若干组数据,每组数据第一行 n, n 为 0,表示输入结束,接着输入 n 行数据,每行 2 个数据,表示速度 v 和出发时间 t ,如果 t<0,表示陪伴人提早出发了。
输出格式
输出对应若干行数据,每行输出 1 个数,表示最快到达的时间。
输入输出样例1
输入
4
20 0
25 -155
27 190
30 240
2
21 0
22 34
0
输出
780
771
说明提示
1≤n≤10000
初始代码
答案错误
cs
//从比上一次速度大的人中找能碰上C的最短时间,即找C下次变化的速度
#include<stdio.h>
#include<stdlib.h>
double cnt(double v_C, double v_other, double s_other, double s_C, double t_before)
{
double t_may = (s_other + s_C - t_before * v_other) / v_other - v_C;
return t_may;
}
typedef struct other {
double v;double t;double s;
}other;
int compare(const void* a, const void* b)
{
double diff = ((other*)a)->v - ((other*)b)->v;
if (diff > 0) return 1;
if (diff < 0) return -1;
return 0;
}
int main()
{
int n;
while (scanf("%d", &n) == 1)
{
if (n == 0)
break;
double v = 0.0, t_before = 0.0, s = 0.0;
other o[10000] = { 0.0,0.0,0.0 };
int m = 0;
for (int i = 0;i < n;i++)
{
int a, b;
scanf("%d %d", &a, &b);
if (b == 0)//初始化起点最大速度(如果有0时刻出发的)
{
if ((double)a > v)
v = (double)a;
}
//提早出发的人要么赶不上,要么赶上时速度比他大,即不变速
if (b > 0)
{
o[m].v = (double)a;
o[m].t = (double)b;
o[m].s = o[m].t * o[m].v;
m++;
}
}
qsort(o, m, sizeof(other), compare);//按速度升序排序
int n_v = 0;
for (int i = 0;i < m;i++)
{
if (o[i].v > v)//找比之前速度大的速度
{
n_v = i;
break;
}
}
double t_diff[10000] = { 0.0 };
while (s <= 4500.0)
{
double min_t = 5000, v_copy = v, s_copy = s, t_copy = t_before;
for (int i = n_v;i < m;i++)
{
double t = cnt(v_copy, o[i].v, o[i].s, s_copy, t_copy);
if (min_t > t)//改变速度为最先能与C同路的人的速度
{
min_t = t;
v = o[i].v;
t_before = t_copy + min_t;
s = s_copy + v_copy * min_t;
n_v = i;
}
}
if (s > 4500)
{
t_before = t_copy + (4500 - s_copy) / v_copy;
}
}
int t_result = (int)t_before + 1;
printf("%d\n", t_result);
}
return 0;
}
反思问题
一开始想通过模拟算法,计算Charley从起点到终点的整个变速过程,进而得到时间。忽略了可从
Charley最后会与一人同时到达终点的角度思考。
题目理解的关键点
Charley 的规则:
-
必须有人陪伴(同速骑行)
-
遇到更快的人就加速跟上
-
出发时间是 0
关键推理:
-
如果 Charley 最终和某人同时到达终点,那么他的到达时间就是那个人的到达时间
-
他会在路上遇到不同的人并加速,但最终会跟着最快的人到达
-
对于 t < 0 的人(提前出发),Charley 在起点无法和他们一起出发,所以不考虑
最终AC代码
cs
#include <stdio.h>
#include <math.h>
#include <limits.h>
int main() {
int n;
while (scanf("%d", &n) == 1 && n != 0) {
int ans = INT_MAX;
for (int i = 0; i < n; i++) {
int v, t;
scanf("%d %d", &v, &t);
if (t < 0) continue;
// 路程 4.5 km, v km/h
// 时间 = t + 4.5 / v * 3600 秒
int time = t + (int)ceil(4.5 / v * 3600);
if (time < ans) ans = time;
}
printf("%d\n", ans);
}
return 0;
}
函数拓展
一、limits.h 头文件
1. 作用
定义各种整数类型的极限值常量
2. 主要常量
| 常量 | 含义 | 典型值 |
|---|---|---|
INT_MAX |
int 最大值 | 2147483647 |
INT_MIN |
int 最小值 | -2147483648 |
UINT_MAX |
unsigned int 最大值 | 4294967295 |
LONG_MAX |
long 最大值 | 2147483647 |
CHAR_BIT |
一个字节的位数 | 8 |
CHAR_MAX |
char 最大值 | 127 |
SCHAR_MAX |
signed char 最大值 | 127 |
SCHAR_MIN |
signed char 最小值 | -128 |
3. 使用示例
cs
#include <stdio.h>
#include <limits.h>
int main() {
printf("INT_MAX = %d\n", INT_MAX);
printf("INT_MIN = %d\n", INT_MIN);
int ans = INT_MAX; // 常用作最小值查找的初始值
return 0;
}
4. 应用场景
-
初始化变量为最大值/最小值
-
边界检查
-
溢出检测
二、math.h 中的取整函数
1. 函数概览
| 函数 | 功能 | 原型 |
|---|---|---|
ceil() |
向上取整 | double ceil(double x) |
floor() |
向下取整 | double floor(double x) |
round() |
四舍五入 | double round(double x) |
trunc() |
向零取整 | double trunc(double x) |
2. 详细说明
ceil() - 向上取整
#include <math.h>
double ceil(double x); // 返回 ≥ x 的最小整数
示例:
ceil(2.3) = 3.0
ceil(2.7) = 3.0
ceil(-2.3) = -2.0
ceil(-2.7) = -2.0
floor() - 向下取整
#include <math.h>
double floor(double x); // 返回 ≤ x 的最大整数
示例:
floor(2.3) = 2.0
floor(2.7) = 2.0
floor(-2.3) = -3.0
floor(-2.7) = -3.0
round() - 四舍五入
#include <math.h>
double round(double x); // 返回最接近的整数
示例:
round(2.3) = 2.0
round(2.7) = 3.0
round(2.5) = 3.0
round(-2.3) = -2.0
round(-2.7) = -3.0
round(-2.5) = -3.0
trunc() - 向零取整
#include <math.h>
double trunc(double x); // 去掉小数部分
示例:
trunc(2.3) = 2.0
trunc(2.7) = 2.0
trunc(-2.3) = -2.0
trunc(-2.7) = -2.0
3. 对比表格
| 数值 | ceil | floor | round | trunc |
|---|---|---|---|---|
| 2.3 | 3.0 | 2.0 | 2.0 | 2.0 |
| 2.7 | 3.0 | 2.0 | 3.0 | 2.0 |
| -2.3 | -2.0 | -3.0 | -2.0 | -2.0 |
| -2.7 | -2.0 | -3.0 | -3.0 | -2.0 |