计费时段计算
2026 华为OD机试真题 4月22日华为OD上机新系统考试真题 100 分题型
点击查看华为 OD 机试真题完整目录:2026最新华为OD机试新系统卷 + 双机位C卷 真题题库目录|全覆盖题库 + 逐点算法考点详解
题目描述
电力公司的电费根据用电的时间,采用三挡计费:
第一档:用电时间在每天的12 : 00 12:0012:00-13 : 30 13:3013:30和17 : 30 17:3017:30-18 : 00 18:0018:00
第二档:每天从0 : 00 0:000:00起的,且不在第一档时段内的,累积的10 1010小时
第三档:其他时段
某设备每天开关机一次(0 : 00 0:000:00之前必然关机)。统计这台设备每天各个时段的开机时长,用分钟表示。
时间格式:H H : M M HH:MMHH:MM,24 2424小时制 说明:小时不足两位不补零,分钟严格保持两位。例如:8 : 08 8:088:08
输入描述
“H H : M M HH:MMHH:MMH H : M M HH:MMHH:MM”,两个时间分别为设备开机时间、设备关机时间,中间空格间隔。例如:“8 : 00 8:008:0023 : 30 23:3023:30”。
约束:
- 结束时间不超过0 : 00 0:000:00(最大为23 : 59 23:5923:59),即不考虑跨天的情况。
- 如果开机时间跟关机时间相等,则认为是开机0 00分钟。例如:“8 : 00 8:008:008 : 00 8:008:00”
输出描述
整数数组,依次为第一、二、三档的时长,单位:分钟。例如:[ 120 , 600 , 210 ] [120,600,210][120,600,210]
示例1
输入
8:00 23:30输出
[120,600,210]说明
- 第一档:12 : 00 12:0012:00-13 : 30 13:3013:30、17 : 30 17:3017:30-18 : 00 18:0018:00,共120 120120分钟
- 第二档:8 : 00 8:008:00-12 : 00 12:0012:00、13 : 30 13:3013:30-17 : 30 17:3017:30、18 : 00 18:0018:00-20 : 00 20:0020:00,共600 600600分钟,达到10 1010小时上限。其余的时间要归到第三档
- 第三档:20 : 00 20:0020:00-23 : 30 23:3023:30,共210 210210分钟
示例2
输入
13:00 17:45输出
[45,240,0]说明
- 第一档:13 : 00 13:0013:00-13 : 30 13:3013:30、17 : 30 17:3017:30-17 : 45 17:4517:45,共45 4545分钟
- 第二档:13 : 30 13:3013:30-17 : 30 17:3017:30,共240 240240分钟
- 第三档:由于第二档还没达到10 1010小时,第三档时间为0 00
解题思路
核心思想
- 时间转换:将所有输入的时间格式(HH:MM)转换为从当天0 : 00 0:000:00开始的总分钟数,方便计算。
- 档位规则:
- 第一档:固定时段12 : 00 12:0012:00-13 : 30 13:3013:30(720 720720-810 810810分钟)和17 : 30 17:3017:30-18 : 00 18:0018:00(1050 10501050-1080 10801080分钟)。
- 第二档:非第一档时段内的开机时间,每天累积上限为10 1010小时(600 600600分钟)。
- 第三档:超过第二档上限后的所有其他开机时间。
- 模拟计算:从开机时间遍历到关机时间,每一分钟判断其属于哪一档:
- 如果当前分钟在第一档时段内,计入第一档。
- 如果不在第一档时段:
- 如果已计入第二档的时间未满600 600600分钟,计入第二档。
- 否则,计入第三档。
- 输出结果:以数组形式输出三个档位的总时长。
复杂度分析
- 时间复杂度:O ( L ) O(L)O(L),其中L LL是开关机之间的时间跨度(分钟)。由于一天最多只有1440 14401440分钟,因此计算非常高效。
- 空间复杂度:O ( 1 ) O(1)O(1),只需要常数级别的变量来存储各档位的时间。
Java
importjava.util.Scanner;/** * 华为OD机试 - 计费时段计算 */publicclassMain{publicstaticvoidmain(String[]args){Scannersc=newScanner(System.in);if(!sc.hasNext())return;// 读取开机和关机时间StringstartStr=sc.next();StringendStr=sc.next();intstart=toMinutes(startStr);intend=toMinutes(endStr);inttier1=0;inttier2=0;inttier3=0;inttier2Limit=600;// 第二档上限 600 分钟// 逐分钟进行模拟计算for(inti=start;i<end;i++){if(isTier1(i)){tier1++;}else{if(tier2<tier2Limit){tier2++;}else{tier3++;}}}// 输出结果格式 [T1, T2, T3]System.out.println("["+tier1+","+tier2+","+tier3+"]");}/** * 将 HH:MM 格式转换为总分钟数 */privatestaticinttoMinutes(Stringtime){String[]parts=time.split(":");returnInteger.parseInt(parts[0])*60+Integer.parseInt(parts[1]);}/** * 判断当前分钟是否属于第一档时段 * 第一档:12:00-13:30 (720-810) 和 17:30-18:00 (1050-1080) */privatestaticbooleanisTier1(intm){return(m>=720&&m<810)||(m>=1050&&m<1080);}}Python
importsysdefto_minutes(t_str):"""将 HH:MM 转换为分钟"""h,m=map(int,t_str.split(':'))returnh*60+mdefis_tier1(m):"""判断是否为第一档时段"""# 12:00-13:30 (720-810), 17:30-18:00 (1050-1080)return(720<=m<810)or(1050<=m<1080)defsolve():# 读取输入line=sys.stdin.read().strip()ifnotline:returntimes=line.split()iflen(times)<2:returnstart=to_minutes(times[0])end=to_minutes(times[1])t1,t2,t3=0,0,0t2_limit=600# 模拟每一分钟forminrange(start,end):ifis_tier1(m):t1+=1else:ift2<t2_limit:t2+=1else:t3+=1# 格式化输出print(f"[{t1},{t2},{t3}]")if__name__=="__main__":solve()JavaScript
constreadline=require('readline');constrl=readline.createInterface({input:process.stdin,terminal:false});rl.on('line',(line)=>{if(!line.trim())return;constparts=line.trim().split(/\s+/);if(parts.length<2)return;consttoMinutes=(t)=>{const[h,m]=t.split(':').map(Number);returnh*60+m;};conststart=toMinutes(parts[0]);constend=toMinutes(parts[1]);lett1=0,t2=0,t3=0;constt2Limit=600;// 逐分钟判断for(letm=start;m<end;m++){// 第一档判断if((m>=720&&m<810)||(m>=1050&&m<1080)){t1++;}else{// 第二、三档判断if(t2<t2Limit){t2++;}else{t3++;}}}console.log(`[${t1},${t2},${t3}]`);});C++
#include<iostream>#include<string>#include<vector>#include<sstream>usingnamespacestd;/** * 将 HH:MM 格式的时间转换为分钟 */inttoMinutes(string t){inth,m;sscanf(t.c_str(),"%d:%d",&h,&m);returnh*60+m;}/** * 判断是否属于第一档 */boolisTier1(intm){return(m>=720&&m<810)||(m>=1050&&m<1080);}intmain(){string s1,s2;if(!(cin>>s1>>s2))return0;intstart=toMinutes(s1);intend=toMinutes(s2);intt1=0,t2=0,t3=0;intt2Limit=600;// 模拟计算for(inti=start;i<end;++i){if(isTier1(i)){t1++;}else{if(t2<t2Limit){t2++;}else{t3++;}}}cout<<"["<<t1<<","<<t2<<","<<t3<<"]"<<endl;return0;}Go
packagemainimport("fmt""strings")// 将 HH:MM 转换为分钟functoMinutes(tstring)int{varh,mintfmt.Sscanf(t,"%d:%d",&h,&m)returnh*60+m}funcmain(){vars1,s2string// 读取两个时间字符串if_,err:=fmt.Scan(&s1,&s2);err!=nil{return}start:=toMinutes(s1)end:=toMinutes(s2)t1,t2,t3:=0,0,0t2Limit:=600// 逐分钟计费fori:=start;i<end;i++{// 判断是否在第一档时段if(i>=720&&i<810)||(i>=1050&&i<1080){t1++}else{// 第二档和第三档ift2<t2Limit{t2++}else{t3++}}}// 按照 [T1,T2,T3] 格式输出fmt.Printf("[%d,%d,%d]\n",t1,t2,t3)}C语言
#include<stdio.h>/** * 将时间字符串 HH:MM 转换为总分钟数 */intto_minutes(char*t){inth,m;sscanf(t,"%d:%d",&h,&m);returnh*60+m;}intmain(){chars1[10],s2[10];// 读取开机和关机时间if(scanf("%s %s",s1,s2)!=2)return0;intstart=to_minutes(s1);intend=to_minutes(s2);intt1=0,t2=0,t3=0;intt2_limit=600;// 逐分钟累加计费时长for(inti=start;i<end;i++){// 第一档时段判断if((i>=720&&i<810)||(i>=1050&&i<1080)){t1++;}else{// 第二档及第三档判断if(t2<t2_limit){t2++;}else{t3++;}}}// 打印结果printf("[%d,%d,%d]\n",t1,t2,t3);return0;}完整用例
用例1
8:00 23:30用例2
13:00 17:45用例3
12:00 13:30用例4
0:00 10:00用例5
12:00 12:00用例6
20:00 23:59用例7
11:59 12:01用例8
17:29 18:01用例9
0:00 23:59用例10
13:30 17:30文章目录
- 计费时段计算
- 题目描述
- 输入描述
- 输出描述
- 示例1
- 示例2
- 解题思路
- 核心思想
- 复杂度分析
- Java
- Python
- JavaScript
- C++
- Go
- C语言
- 完整用例
- 用例1
- 用例2
- 用例3
- 用例4
- 用例5
- 用例6
- 用例7
- 用例8
- 用例9
- 用例10