湘大头歌程-Ride to Office练习笔记

题目描述

起点与终点相隔 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
相关推荐
STY_fish_201231 分钟前
P11855 [CSP-J2022 山东] 部署
算法·图论·差分
H_BB33 分钟前
算法详解:滑动窗口机制
数据结构·c++·算法·滑动窗口
淀粉肠kk34 分钟前
【C++】封装红黑树实现Mymap和Myset
数据结构·c++
Zero-Talent34 分钟前
“栈” 算法
算法
橘子编程35 分钟前
经典排序算法全解析
java·算法·排序算法
waeng_luo35 分钟前
【鸿蒙开发实战】智能数据洞察服务:待回礼分析与关系维护建议算法
算法·ai编程·鸿蒙
风筝在晴天搁浅35 分钟前
代码随想录 279.完全平方数
算法
不穿格子的程序员39 分钟前
从零开始刷算法——字串与区间类经典题:前缀和 + 单调队列双杀
算法·前缀和·哈希表·双向队列·单调队列
坚持就完事了39 分钟前
十大排序算法
数据结构·算法·排序算法