洛谷 普及【上学迟到】简单逻辑以及代码实现

计算最晚出门时间
本文介绍了一个计算学生在不迟到前提下最晚出门时间的方法。通过输入学生家到学校的距离和步行速度,结合学校规定的到达时间,计算出最迟出发时间。

#题目
题目描述

学校和 yyy 的家之间的距离为 sss 米,而 yyy 以 vvv 米每分钟的速度匀速走向学校。

在上学的路上,yyy 还要额外花费 101010 分钟的时间进行垃圾分类。

学校要求必须在上午 8:00\textrm{8:00}8:00 到达,请计算在不迟到的前提下,yyy 最晚能什么时候出门。

由于路途遥远,yyy 可能不得不提前一天出发,但是提前的时间不会超过一天。
输入格式

一行两个正整数 s,vs,vs,v,分别代表路程和速度。
输出格式

输出一个 242424 小时制下的时间,代表 yyy 最晚的出发时间。

输出格式为 HH:MM\texttt{HH:MM}HH:MM,分别代表该时间的时和分。必须输出两位,不足前面补 000。
输入输出样例
输入 #1

100 99

输出 #1

07:48

说明/提示

对于 100%100%100% 的数据,1≤s,v≤1041 \le s,v \le 10^41≤s,v≤104。

我的题解
画一条长度为s的进度条,每秒钟进度条前进v(个人觉得按秒来比较合适,精确而又不太复杂,当然强迫症大佬们也可以按毫秒……体验极致的精确),得到总秒数,然后从8:00往前倒着读秒(一分钟60s一小时3600s),就不用什么讨论讨论讨论了……

	***(相当于一个刚学会除法的小朋友买了个倒着走的电子钟,盯着电子钟睁大眼睛读秒……)***

刚接触C的小蒻苣,

个人代码实现

#include <stdio.h>

int Min_Clock(int TTL_SEC);
int Hour_Clock(int TTL_SEC);//其实这两个函数是一样的,只不过返回值不一样
                            //一个返回时间中的小时,一个返回时间中的分钟 
int main()
{
	long int s, v, TIME, min, hour;
	
	scanf("%d%d", &s, &v);
	
	TIME = s / ((float)v / 60.0) + 600;
	
	min = Min_Clock(TIME);
	hour = Hour_Clock(TIME);
	
	if(hour < 10)
		printf("0%d:", hour);
	else
		printf("%d:",hour);
		
	if(min < 10)
		printf("0%d", min);
	else
		printf("%d", min);
	

 	return 0;
}

int Min_Clock(int TTL_SEC) //输入时钟需要走的总秒数
{
	 int HOUR = 8, MIN = 0, SEC = 0;//时钟的初始时间:八点整;
	 
	 while(TTL_SEC != 0)//这里是倒着走的电子钟
	 {
	 	TTL_SEC--;
	 	
	 	if(SEC == 0)
	 	{
	 		if(MIN == 0)
	 		{
	 			if(HOUR == 0)
	 				HOUR = 23;
				else
					HOUR--;
					
				MIN = 59;
			}
			else
				MIN--;
			
	 		SEC = 59;
		}
		else
			SEC--;	
	 }
	 
	 return MIN;
}

int Hour_Clock(int TTL_SEC) //其实这个函数就是复制上面个函数来的,改了名字和返回值
{
	 int HOUR = 8, MIN = 0, SEC = 0;//时钟的初始时间:八点整;
	 
	 while(TTL_SEC != 0)
	 {
	 	TTL_SEC--;
	 	
	 	if(SEC == 0)
	 	{
	 		if(MIN == 0)
	 		{
	 			if(HOUR == 0)
	 				HOUR = 23;
				else
					HOUR--;
					
				MIN = 59;
			}
			else
				MIN--;
			
	 		SEC = 59;
		}
		else
			SEC--;	
	 }
	 
	 return HOUR;
}

<think> 我们被要求使用C语言解决P5707上学迟到问题。根据引用内容,我们可以总结出以下关键点: 1. 问题描述:小明必须在8:00到达学校。输入两个整数:s(路程,单位v(速度,单位/分)。另外,他需要10分钟垃圾分类时间。 2. 计算总时间:走路时间(t1 = s/v,注意向上取整)加上垃圾分类时间(10分钟)。 3. 出发时间:从8:00往前推总时间(即减去总分钟数),如果时间跨越到前一天,需要用24小时制处理。 4. 输出格式:24小时制,小时分钟都是两位数,不足两位的前面补0(例如01:05)。 根据引用[5]的代码,我们可以看到一个较为简洁的解决方案: - 计算走路时间:如果路程s不能被速度v整除,则需要加1(向上取整)。 - 总时间 = 走路时间 + 10分钟(垃圾分类)。 - 用8:00(即480分钟,因为8*60=480)减去总时间,得到出发时间相对于00:00的分钟数(可能是负数)。 - 如果得到的时间是负数,则加上24*60(即一天的分钟数)得到前一天的出发时间。 - 然后,将总分钟数转换为小时分钟,并用%02d格式化输出。 但是,引用[3]、[4]中提到了另一种处理方式:直接计算出发时间的小时分钟,并分情况讨论(是否超过8小时等)。而引用[5]的方法更简洁,通过将时间转换为分钟数,然后统一处理负数情况(加上24*60)即可。 我们采用引用[5]的方法,因为其逻辑清晰且代码简洁。 步骤: 1. 读入sv。 2. 计算走路时间t1 = s/v,如果s%v不为0,则t1加1(因为不足1分钟的部分需要1分钟)。 3. 总时间T = t1 + 10。 4. 计算从00:00到8:00的分钟数(480分钟),那么出发时间应该为480 - T分钟(相对于00:00)。 如果480-T是负数,说明出发时间在前一天,那么加上24*60(即1440分钟)使其变为正数(表示前一天的某个时间点,但用24小时制表示就是前一天的同一时刻)。 5. 注意:由于时间循环的特性,加上1440分钟后,时间在0~1439分钟之间。然后计算小时分钟。 6. 小时 = (480 - T + 24*60) % (24*60) 然后除以60,分钟取模60。但注意,当480-T为负数时,加上24*60后得到的是从00:00开始往前推的时间(即前一天的某个时间),但这样计算后小时分钟就是正确的24小时制表示。 然而,更简单的做法是:先计算time = 480 - T,如果time<0,则time+=24*60。然后用time除以60得到小时,取模60得到分钟。 7. 输出时,小时分钟都用%02d格式,保证两位数字,不足两位前面补0。 但是,注意引用[5]的代码中,当time小于0时,加上24*60,然后计算小时分钟。这样得到的出发时间是正确的。 然而,我们需要注意:题目要求提前的时间不会超过一天,所以加上24*60一次就够了。 因此,我们按照引用[5]的代码思路: int s, v; scanf("%d %d", &s, &v); int t = s / v; if (s % v != 0) t++; // 向上取整 t += 10; // 加上垃圾分类时间 // 计算出发时间(分钟数,从00:00开始,8:00对应480分钟) int total_minutes = 8 * 60 - t; // 从00:00开始,8:00减去总用时得到出发时间的分钟数(可能是负的) if (total_minutes < 0) { total_minutes += 24 * 60; // 加上一天的分钟数,变成前一天的时间(用24小时制表示) } int hour = total_minutes / 60; int minute = total_minutes % 60; // 输出,注意格式:两位数字,不足补0 printf("%02d:%02d", hour, minute); 但是,测试一下:如果s=100, v=99,则t1=2(100/99=1,余1,所以t1=2),总时间t=12分钟。total_minutes=480-12=468分钟,即7小时48分钟,所以输出07:48?不对,应该是7小时48分钟,但是8点往前推12分钟是07:48。 但是,题目要求输出的是出发时间,也就是应该输出07:48(即7:48)。但是我们的计算:468分钟=7小时48分钟(468/60=7余48),所以输出07:48。 然而,注意题目要求:输出24小时制,小时分钟都是两位,所以07:48是正确的。 但是,我们再看一个例子:如果s=10000, v=1,则走路时间10000分钟,加上10分钟是10010分钟。那么480-10010 = -9530。然后加上24*60=1440,得到-9530+1440=-8090,还是负数,所以需要多次加?但题目说提前的时间不会超过一天,所以只需要加一次1440分钟就够了(即提前的时间在24小时以内)?题目原话:“提前的时间不会超过一天”。所以,480-t可能是负数,且绝对值最大为24*60-1(因为提前不超过一天),所以加上一次24*60即可将其调整到0到24*60-1之间。 但是,在引用[5]的代码中是加上24*60一次,所以我们的代码也只需要加一次。 修正:上面的例子中,-9530+24*60=-9530+1440=-8090,还是不对。这是因为10010分钟远远超过了24小时(24*60=1440分钟),而题目只保证提前的时间不超过一天,也就是说总时间T最大不会超过480+24*60=1920分钟(即8:00加上24小时)。因为提前不超过一天,那么T最大为480+24*60=1920分钟。所以我们的例子中s=10000,v=1,走路时间10000分钟已经超过了1920分钟,但题目数据范围:1≤s,v≤10000。所以可能T的最大值会达到10000/1+10=10010分钟,这远远超过1920分钟(32小时),与题目“提前的时间不会超过一天”(即24小时)矛盾。所以题目数据范围下,T最大为10000(s最大,v最小为1)分钟,那么480-10010=-9530,需要加上几个24*60?题目保证提前的时间不超过一天,所以实际上T最多为480+24*60=1920分钟?但10000>1920,所以矛盾。 重新看题目:题目说“提前的时间不会超过一天”,意思是最坏情况会提前24小时(即前一天出发)。所以我们的算法没问题:当480-T为负数时,加上24*60后,这个值应该在0到24*60-1之间(因为提前最多24小时,所以480-T最小为-24*60+1?不对,480-T最小可以是-24*60+?)。实际上,提前不超过一天,也就是说出发时间最早是前一天的8:00(因为如果提前超过24小时,那么出发时间就会更早)。题目规定提前的时间不超过24小时,所以480-T的范围是[-24*60, 0),加上24*60后,范围就是[0, 24*60)。所以我们的代码只需要加一次24*60。 但是,上述例子(s=10000,v=1)中,T=10010分钟,480-10010=-9530,加上24*60=-9530+1440=-8090,还是负数,说明提前的时间已经超过了24小时(因为-8090分钟相当于提前了8090分钟,即134.83小时,超过5天)。这不符合题目“提前的时间不超过一天”的条件。因此,题目数据范围1≤s,v≤10000的情况下,可能出现提前时间超过一天的情况吗? 题目描述中明确说:“提前的时间不会超过一天”。所以测试数据保证T的最大值不会超过480+24*60=1920分钟?但s最大为10000,v最小为1,T=10000+10=10010>1920。这样就矛盾了。 所以,我们需要重新审视题目。引用[3]中提到了两个坑,其中一个是“提前的时间不会超过一天”,所以我们的算法应该能够处理不超过一天的情况(即480-T最小为-1439分钟,因为480-T最小为-24*60+1?实际上,最大提前时间为24小时即1440分钟,所以480-T最小为480-(480+1440)=-1440分钟?不对,提前的时间就是T分钟,因为8:00减去T分钟就是出发时间,提前时间最多为24小时,即T最大为1440+480=1920分钟?不对,提前时间T分钟,如果T=480分钟,则出发时间是0:00;如果T=481分钟,则出发时间是前一天的23:59(因为480-481=-1,加上24*60=1440,得到1439分钟,即23:59)。所以T最大为480+24*60=1920分钟(即提前一天整)。 因此,题目数据范围1≤s,v≤10000,但实际测试数据中,sv的取值会保证T(总时间)小于等于1920分钟吗?题目没有明确,但是引用[5]的数据范围是100%数据1≤s,v≤10000,所以可能存在T>1920的情况吗? 我们再看引用[5]的代码,它只加了一次24*60,所以对于T>480+24*60的情况,它无法正确处理。例如T=1921,则480-1921=-1441,加上24*60=-1441+1440=-1,还是负数,然后输出就会错误。 因此,我们需要一个更健壮的方法:计算出发时间相对于00:00的分钟数,即: 出发时间分钟数 = (480 - T + 24*60) % (24*60) 但是,负数取模在不同语言中行为不同。在C语言中,负数取模的结果是负数。所以我们可以先加上足够的24*60(比如两倍)保证为正,然后取模24*60。 改进:为了避免负数问题,我们可以这样计算: 首先,将8:00(480分钟)加上24小时的分钟数(1440分钟)得到32:00(相当于前一天的8:00),然后减去总时间T,得到出发时间(相对于00:00的分钟数,但可能超过24小时)。然后模24*60,得到在0~1439分钟之间的分钟数。 即:total_minutes = (480 + 24*60 - T) % (24*60); 注意:这个式子中,480+24*60=1920,减去T后,如果T小于1920,那么结果在0~1919之间,模1440(24*60)后,得到的结果在0~1439之间。但是,如果T>1920,那么1920-T为负数,负数模1440在C语言中会得到负数(我们不希望这样)。所以我们需要保证1920-T为正数?题目保证提前不超过一天,所以T最大为1920,所以1920-T>=0?不对,题目说提前不超过24小时,即T最大为480+24*60=1920分钟(因为8:00往前推24小时就是前一天的8:00)。所以T最大为1920分钟。因此,1920-T>=0。 因此,我们可以这样计算: 出发时间分钟数 = (1920 - T) % 1440; 但是,模运算在这里是为了处理T大于1920的情况?不对,根据题目,T最大1920,所以1920-T>=0,那么模1440就是它本身(因为小于1440的倍数)。所以这个模运算多余了。 所以,我们只需要计算 total_minutes = 1920 - T; // 这个值在0~1920之间,然后我们只需要模1440?不对,因为1920-0=1920>1440,所以我们模1440:1920-1440=480,而480分钟是8小时,也就是08:00。但实际上,如果T=0,那么出发时间是前一天的8:00?不对,应该是当天的8:00(即8:00出发)?不对,应该提前0分钟,所以出发时间就是8:00。但题目要求8:00到,所以总时间T=0不可能(因为至少需要10分钟垃圾分类?而且路程>0?)。 另外,如果T=480,那么1920-480=1440分钟,1440分钟就是24:00,即00:00(第二天的00:00)?但题目是24小时制,应该输出00:00。但是,1440%1440=0,所以小时=0,分钟=0,输出00:00。 因此,我们可以用: total_minutes = (1920 - T) % 1440; 然后小时=total_minutes/60, 分钟=total_minutes%60。 但是,考虑T=1920的情况:1920-1920=0,输出00:00(即0点0分)?但是,我们期望的是:提前一天整(24小时)出发,那么在8:00减去1920分钟(1920分钟=32小时)?不对,1920分钟=32小时,那么8:00减去32小时,应该是前一天的0:00(即24小时制的前一天的00:00,也可以说成是当天的00:00?不对,实际上是前一天的00:00,但是用24小时制表示,我们输出00:00,也就是当天的0点?但实际上是前一天的0点。题目要求输出24小时制,所以00:00表示前一天的0点(也就是当天的凌晨0点)?但是我们的计算中,1920-T=0,模1440=0,所以输出00:00,这是正确的,因为提前32小时(即1天8小时)出发,那么出发时间就是前一天的00:00?不对,提前32小时,8:00往前推32小时,就是前一天的0:00(因为32=24+8,所以8:00-8小时=0:00,再减24小时就是前一天的0:00)。所以输出00:00代表前一天的0点,正确。 然而,题目保证提前的时间不超过一天(24小时),所以T最大为1920分钟(即32小时)?不对,题目说提前的时间不超过一天,即提前时间不超过24小时(即1440分钟)。因此,T最大为480+1440=1920分钟(即32小时),没错。所以我们的计算方法成立。 因此,代码可以写为: int T_total = s / v + 10; if (s % v != 0) T_total++; int total_minutes = (1920 - T_total) % 1440; // 1920=480+1440 // 但是,如果(1920-T_total)是负数怎么办?因为题目保证T_total<=1920,所以不会负数。 小时 = total_minutes / 60; 分钟 = total_minutes % 60; 然后输出:printf("%02d:%02d", hour, minute); 但是,测试T_total=480(即8小时):1920-480=1440,1440%1440=0,所以hour=0, minute=0,输出00:00。但是,8:00减去480分钟(8小时)应该是0:00(即00:00),正确。 然而,另一种情况:T_total=479分钟,则1920-479=1441,1441%1440=1分钟,即小时=0,分钟=1,输出00:01。但实际上,8:00减去479分钟,479分钟=7小时59分钟,所以出发时间应该是0:01(因为8:00-7小时59分钟=0:01)。正确。 但是,再测试T_total=481分钟:1920-481=1439分钟,1439%1440=1439,小时=23,分钟=59,所以输出23:59。而8:00减去481分钟:481分钟=8小时1分钟,所以出发时间应该是前一天的23:59(因为8:00-8小时1分钟=前一天的23:59)。正确。 因此,这个方法正确。 但是,我们也可以使用引用[5]的方法(先计算480-T,如果负数加1440),因为题目保证T<=1920,所以480-T最小为480-1920=-1440,然后加上1440得到0(刚好是00:00),所以引用[5]的方法也是正确的。 为了代码清晰,我们选择引用[5]的方法(更直观)。 因此,最终代码: int s, v; scanf("%d %d", &s, &v); int t = s / v; if (s % v != 0) { t++; // 向上取整 } t += 10; // 总耗时 int minutes = 8 * 60 - t; // 8:00的分钟数减去总耗时 if (minutes < 0) { minutes += 24 * 60; // 加上一天的分钟数 } // 现在minutes在0~1439之间(即一天的分钟数) int hour = minutes / 60; int minute = minutes % 60; printf("%02d:%02d", hour, minute); 但是,注意:minutes有可能为0,那么hour=0, minute=0,输出00:00,正确。 因此,我们按照这个思路写代码。 但是,引用[5]的代码中,有一个变量time,其计算为8*60-t,然后如果time小于0就加上24*60。然后输出用%02d,所以是可行的。 所以,我们按照引用[5]的代码来写。 但是,我们注意到引用[5]的代码中,计算走路时间时,先计算t = s / v,然后如果s%v不为0则t++。然后t+=10。然后time=8*60-t。然后处理负数。输出用%02d格式化。 因此,我们直接采用引用[5]的代码作为最终答案。 但是,注意引用[5]的代码中,在计算time=8*60-t后,如果time小于0,则加上24*60(即1440)。然后小时=time/60,分钟=time%60,然后用%02d输出。 代码如下: </think> ### 使用C语言解决P5707上学迟到问题的方法 #### 问题分析 小明必须在8:00到达学校,给定两个参数: - `s`:学校距离) - `v`:步行速度/分) 额外要求:提前10分钟进行垃圾分类。 需要计算最晚出发时间(24小时制,输出格式为`HH:MM`)。 #### 关键步骤 1. **计算总时间**: - 走路时间 $t_{\text{walk}} = \lceil s / v \rceil$(向上取整) - 总时间 $T = t_{\text{walk}} + 10$(含垃圾分类时间) - 向上取整逻辑:若 $s \mod v \neq 0$,则 $t_{\text{walk}}$ 需加1分钟 2. **计算出发时间**: - 将8:00转换为分钟数:$8 \times 60 = 480$ 分钟 - 出发时间分钟数 $= 480 - T$ - 若结果为负数,说明需前一天出发,需加上 $24 \times 60$ 分钟 3. **时间格式化**: - 小时 $= \text{总分钟数} / 60$ - 分钟 $= \text{总分钟数} \mod 60$ - 输出时用 `%02d` 保证两位数格式(如 7:5 输出为 `07:05`) #### C语言代码实现 ```c #include <stdio.h> int main() { int s, v; // s: 路程(), v: 速度/分) scanf("%d %d", &s, &v); // 1. 计算走路时间(向上取整) int t = s / v; if (s % v != 0) t++; // 有余数时加1分钟 // 2. 计算总时间(含垃圾分类10分钟) t += 10; // 3. 计算出发时间(分钟数) int minutes = 8 * 60 - t; // 8:00转换为分钟 if (minutes < 0) { minutes += 24 * 60; // 跨天处理(提前不超过一天) } // 4. 转换为小时分钟 int hour = minutes / 60; int minute = minutes % 60; // 5. 格式化为HH:MM输出 printf("%02d:%02d", hour, minute); return 0; } ``` #### 代码说明 1. **输入处理**:通过 `scanf` 读取路程 `s` 速度 `v`。 2. **时间计算**: - 走路时间向上取整(避免小数分钟) - 总时间 $T = \lceil s/v \rceil + 10$ 3. **跨天处理**:若 `480 - T < 0`,加上1440分钟(24小时)[^5]。 4. **格式化输出**:`%02d` 确保小时分钟始终为两位数(如 `05:09`)。 #### 示例测试 - **输入**:`100 50` **计算**: $t_{\text{walk}} = \lceil 100/50 \rceil = 2$ 分钟 $T = 2 + 10 = 12$ 分钟 出发时间 $= 480 - 12 = 468$ 分钟 → $7$ 小时 $48$ 分钟 **输出**:`07:48` - **输入**:`3000 10` **计算**: $t_{\text{walk}} = \lceil 3000/10 \rceil = 300$ 分钟 $T = 300 + 10 = 310$ 分钟 出发时间 $= 480 - 310 = 170$ 分钟 → $2$ 小时 $50$ 分钟 **输出**:`02:50`(前一天出发)
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值