湘大头歌程-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
相关推荐
有点。3 小时前
C++03阶段练习(练习题)
数据结构·算法·图论
周末也要写八哥4 小时前
经典算法实例:游戏中弱角色的数量(二)
算法
智者知已应修善业4 小时前
【4060BD_5V应用电路图】2022-12-24
驱动开发·经验分享·笔记·硬件架构·硬件工程
是Yu欸5 小时前
鸿蒙PC移植:2048 从网页小游戏到 AI 桌面应用
大数据·人工智能·算法·数据挖掘·openharmony·codex
鹿角片ljp5 小时前
KV Cache 解析
java·算法
liliangcsdn5 小时前
IVOL与偏度因子的对比测量分析
算法
free-elcmacom5 小时前
C语言字符指针与字符串字面量——从一道“剑指 Offer”笔试题说起
c语言·visual studio
threerocks6 小时前
Jev 入门第一课
算法
西柚研究生1234567 小时前
论文分析17:YOLOv11_UAVNet:无人机航拍图像专用目标检测算法
人工智能·python·深度学习·算法·目标检测
小李不想当小白7 小时前
DMA直接存储器存取(STM32标准库学习笔记)
笔记·stm32·单片机·嵌入式硬件·学习·分享