华为OD机试C卷(100分)- 手机App防沉迷系统(C语言)

题目描述

智能手机方便了我们生活的同时,也侵占了我们不少的时间。“手机App防沉迷系统”能够让我们每天合理地规划手机App使用时间,在正确的时间做正确的事。

它的大概原理是这样的:

在一天24小时内,可以注册每个App的允许使用时段
一个时间段只能使用一个App
App有优先级,数值越高,优先级越高。注册使用时段时,如果高优先级的App时间和低优先级的时段有冲突,则系统会自动注销低优先级的时段,如果App的优先级相同,则后添加的App不能注册。
请编程实现,根据输入数据注册App,并根据输入的时间点,返回时间点使用的App名称,如果该时间点没有注册任何App,请返回字符串“NA”。

输入描述

第一行表示注册的App数量 N(N ≤ 100)

第二部分包括 N 行,每行表示一条App注册数据

最后一行输入一个时间点,程序即返回该时间点使用的App

2
App1 1 09:00 10:00
App2 2 11:00 11:30
09:30

数据说明如下:

N行注册数据以空格分隔,四项数依次表示:App名称、优先级、起始时间、结束时间
优先级1~5,数字越大,优先级越高
时间格式 HH:MM,小时和分钟都是两位,不足两位前面补0
起始时间需小于结束时间,否则注册不上
注册信息中的时间段包含起始时间点,不包含结束时间点

输出描述

输出一个字符串,表示App名称,或NA表示空闲时间

用例

输入 1
App1 1 09:00 10:00
09:30
输出 App1
说明 App1注册在9点到10点间,9点半可用的应用名是App1

输入 2
App1 1 09:00 10:00
App2 2 09:10 09:30
09:20
输出 App2
说明 App1和App2的时段有冲突,App2优先级高,注册App2之后,App1自动注销,因此输出App2。

输入 2
App1 1 09:00 10:00
App2 2 09:10 09:30
09:50
输出 NA
说明 无

题目解析

本题数量级较小,可以考虑暴力破解。

本题每注册一个App_registering前,都要去和已注册的所有App_registered进行比较:

注册时段是否有冲突?
如果没有冲突,则继续和下一个App_registered比较
如果有冲突,则比较优先级

2.1. App_registering 的优先级高于(>)App_registered,则App_registered需要被注销,此时不能直接进行注销动作,因为我们需要确保 App_registering 可以注册后,才能进行注销。

2.2. App_registering 的优先级不高于(≤)App_registered,则App_registering不能注册,即终止后续比较
本题比较两个App注册时段冲突的方式,可以将App的注册时段的时间点信息,转化为分钟数数值,比如:

10:29

可以转化为:

10 * 60 + 29 = 629

这样两个App的时段比较,其实判断两个区间是否有交集,假设两个时段分别为

[s1, e1] 和 [s2, e2]

只要满足

s1 >= e2 或者 s2 >= e1 即可说明两个区间无交集,注意根据题目说明

注册信息中的时间段包含起始时间点,不包含结束时间点

上面两个区间均为左闭右开区间。

且区间保证左边界>右边界,因为题目说明

起始时间需小于结束时间,否则注册不上

即,一个App是否可以注册需要先判断其左边界是否大于右边界

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct APP{
         char name[100];
         int priority;
         int startTime;
         int endTime;
    }APP;
//构造函数
APP *new_app(char *name,int priority,int startTime,int endTime){
     APP *app=(APP*) malloc(sizeof(APP));
     strcpy(app->name,name);
     app->priority=priority;
     app->startTime=startTime;
     app->endTime=endTime;
     return app;
}
//将字符串转换为整型
int convert(char *time){
     int hours;
     int min;
     sscanf(time,"%d:%d",&hours,&min);
     return hours*60+min;

}
APP *apps[100];
int size=0;
void getResult(int queryTime){
    //与前一个注册app比较,无时间冲突则注册成功;有冲突则比较优先级,优先级高的能注册
     APP *registeds[100];
     int registed_size=0;
     for(int i=0;i<size;i++){
          APP *app=apps[i];//当前app
          if(app->endTime<=app->startTime) continue;//结束时间比开始时间早
          int idx[100];//记录被注销app位置
          int idx_size=0;
          int flag=0;
          //和已注册app比较
          for(int j=0;j<registed_size;j++){
               APP *registed=registeds[j];
               if(registed==NULL) continue;//没有已注册app
               //不存在时间冲突
               if(app->endTime<=registed->startTime||registed->endTime<=app->startTime)continue;
               //有时间冲突,比较优先级
               if(app->priority>registed->priority)
                    idx[idx_size++]=j;//注销已注册app
               else{
                   flag=1;
                   break;//优先级低不能注册
               }
          }
          if(flag) continue;
          for(int j=0;j<idx_size;j++){
               registeds[idx[j]]=NULL;
          }
          registeds[registed_size++]=app;//注册成功
     }
     char *ans="NA";
     for(int i=0;i<registed_size;i++){//和已注册app时间比较
        if(registeds[i]==NULL)  continue;
        if(queryTime>=registeds[i]->startTime&&queryTime<registeds[i]->endTime){
          ans=registeds[i]->name;
          break;
        }
     }
     puts(ans);
//printf("%s",ans);
}
int main()
{
    int n;
    scanf("%d",&n);
    for(int i=0;i<n;i++){
     char name[100];
     int priority;
     char start[10];
     char end[10];
     scanf("%s%d%s%s",name,&priority,start,end);

    int startTime=convert(start);
    int endTime=convert(end);
    apps[size++]=new_app(name,priority,startTime,endTime);
    }
    char query[10];
    scanf("%s",query);
    int queryTime=convert(query);
    getResult(queryTime);

    return 0;
}

  • 12
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

我不会起名字呀

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值