湘大头歌程-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
相关推荐
蒸蒸yyyyzwd4 小时前
cpp对象模型学习笔记1.1-2.8
java·笔记·学习
dalong104 小时前
A14:自定义动画演示
笔记·aardio
今儿敲了吗5 小时前
鸿蒙开发第一章学习笔记
笔记·学习·鸿蒙
闪闪发亮的小星星5 小时前
刚体运动学复习笔记
笔记
数研小生5 小时前
构建命令行单词记忆工具:JSON 词库与艾宾浩斯复习算法的完美结合
算法·json
芒克芒克5 小时前
LeetCode 题解:除自身以外数组的乘积
算法·leetcode
Python 老手6 小时前
Python while 循环 极简核心讲解
java·python·算法
@Aurora.6 小时前
优选算法【专题九:哈希表】
算法·哈希算法·散列表
爱看科技6 小时前
微美全息(NASDAQ:WIMI)研究拜占庭容错联邦学习算法,数据安全与隐私保护的双重保障
算法
彷徨而立6 小时前
【C/C++】什么是 运行时库?运行时库 /MT 和 /MD 的区别?
c语言·c++