优先核酸检测点

题目描述

张三要去外地出差,需要做核酸,需要在指定时间点前做完核酸,请帮他找到满足条件的核酸检测点。

  • 给出一组核酸检测点的距离和每个核酸检测点当前的人数;
  • 给出张三要去做核酸的出发时间出发时间是10分钟的倍数,同时给出张三做核酸的最晚结束时间;
  • 题目中给出的距离是整数,单位是公里,时间1分钟为一基本单位;

去找核酸点时,有如下的限制:

  • 去往核酸点的路上,每公里距离花费时间10分钟,费用是10元;
  • 核酸点每检测一个人的时间花费是1分钟;
  • 每个核酸点工作时间都是8点到20点中间不休息,核酸点准时工作,早到、晚到都不检测;
  • 核酸检测结果可立刻知道;
  • 在张三去某个核酸点的路上花费的时间内,此核酸检测点的人数是动态变化的,变化规则是:
    – 在非核酸检测时间内,没有人排排队
    – 8点-10点每分钟增加3人
    – 12点-14点每分钟增加10人
    – 18点-20点每分钟增加20人
    – 其他时间每5分钟增加1人。

要求将所有满足条件的核酸检测点按照优选规则排序列出:优选规则:

  • 花费时间最少的核酸检测点排在前面。
  • 花费时间一样.花费费用最少的核酸检测点排在前面.
  • 时间和费用一样,则ID值最小的排在前面

输入描述

H1 M1
H2 M2
N
ID1 D1 C1
ID2 D2 C2

IDn Dn Cn

解释

H1:当前时间的小时数
M1:当前时间的分钟数
H2:指定完成核算时间的小时数
M2:指定完成核算时间的分钟数
N:所有核酸检测点个数
ID1:核酸点的ID值。
D1:核酸检测点距离张三的距离
C1:核酸检测点当前检测的人数

输出描述

N
l1 T1 M1
12 T2 M2

输出解释

N:满足要求的核酸检测点个数
ln:选择后的核酸检测点ID
Tn:做完核酸花费的总时间(分钟)
Mn:去该核算点花费的费用

题解

java版本

import java.util.*;

public class NucleicAcidPlace {

    public static void main(String[] args) {
        // 当前时间的小时数
        int h1 = 10;
        // 当前时间的分钟数
        int m1 = 30;
        // 指定完成核算时间的小时数
        int h2 = 14;
        // 指定完成核算时间的分钟数
        int m2 = 50;
        // 所有核酸检测点个数
        int n = 3;
        // [ 核酸点的ID值 核酸检测点距离张三的距离 核酸检测点当前检测的人数 ]
        int[][] nucleicAcidLocations = new int[][]{{1, 10, 19}, {2, 8, 20}, {3, 21, 3}};
        printResult(h1, m1, h2, m2, n, nucleicAcidLocations);
    }

    private static void printResult(int h1, int m1, int h2, int m2, int n, int[][] nucleicAcidLocations) {
        // 起始时间,单位分钟
        int startTime = h1 * 60 + m1;
        // 期望张三做核酸的结束时间,注意不能早于8点,不能晚于20点
        int exceptEndTime = Math.min(h2 * 60 + m2, 20 * 60);
        /**
         * 核酸点每检测一个人的时间花费是1分钟
         * 8点-10点每分钟增加3人, 出去1个人,相当于 8点~10点,每分钟增加2人
         * 其他时间每5分钟增加1人 出去1个人 10点~12点,相当于每分钟减少0.8人
         * 12点-14点每分钟增加10人,出去1个人 ,12~14点,相当于每分钟增加9人
         * 其他时间每5分钟增加1人 出去1个人 14~18点,相当于每分钟减少0.8人
         * 18点-20点每分钟增加20人 出去1个人 相当于18~20点,每分钟增加19人
         */
        double[][] times = new double[][]{{8 * 60, 10 * 60, 2}, {10 * 60, 12 * 60, -0.8}, {12 * 60, 14 * 60, 9}, {14 * 60, 18 * 60, -0.8}, {18 * 60, 20 * 60, 19}};
        int len = nucleicAcidLocations.length;
        List<int[]> tempList = new ArrayList<>();
        for (int i = 0; i < len; i++) {
            int[] singleLocation = getSingleLocation(nucleicAcidLocations[i], startTime, exceptEndTime, times, n);
            Optional.ofNullable(singleLocation).ifPresent(tempList::add);
        }
        int newLen = tempList.size();
        int[][] result = new int[newLen][nucleicAcidLocations[0].length];
        for (int i = 0; i < newLen; i++) {
            result[i] = tempList.get(i);
        }
        System.out.println(result.length);
        Arrays.sort(result, (o1, o2) -> {
            if (o1[1] == o2[1]) {
                if (o1[2] == o2[2]) {
                    return o1[0] - o2[0];
                }
                return o1[2] - o2[2];
            }
            return o1[1] - o2[1];
        });
        System.out.println(Arrays.deepToString(result));
    }

    private static int[] getSingleLocation(int[] nucleicAcidLocation, int startTime, int exceptEndTime, double[][] times, int n) {
        // 核酸点id
        int Acid = nucleicAcidLocation[0];
        // 核酸点和张三的距离
        int distance = nucleicAcidLocation[1];
        // 核酸点在张三出发时已有的人数
        int wait = nucleicAcidLocation[2];
        // 每公里距离花费时间10分钟,费用是10元
        int arrived = startTime + distance * 10;
        // 8点之前到
        if (arrived < 8 * 60) {
            // 到达时间就是8点,排在初始人数后面
            arrived = 8 * 60;
            // 选择后的核酸检测点ID  做完核酸花费的总时间(分钟)  去该核算点花费的费用
            return new int[]{Acid, arrived - startTime + wait, distance * 10};
        }
        // 算开始时间
        // 到达时间。然后取交集。在加上增速
        int e1 = arrived;
        for (double[] time : times) {
            double s2 = time[0];
            double e2 = time[1];
            double changePerMin = time[2];
            double t = intersection(startTime, e1, s2, e2);
            // 存在交叉的区间
            if (t > 0) {
                wait += t * changePerMin;
                // 要注意,因为存在的人数减少的情况,所以要跟0取max
                wait = Math.max(0, wait);
            }
        }
        if (startTime + (arrived - startTime + wait) > exceptEndTime) {
            return null;
        }
        return new int[]{Acid, arrived - startTime + wait, distance * 10};
    }

    private static double intersection(double s1, double e1, double s2, double e2) {
        // s2在 s1和e1 之间[s1, e1)。相交的部分就是
        if (s1 <= s2 && s2 < e1) {
            // 开始于s2,结束看e1 和 e2 的最小值
            return Math.min(e1, e2) - s2;
        }
        // s1在[s2, e2)之间
        if (s2 <= s1 && s1 < e2) {
            return Math.min(e1, e2) - s1;
        }
        return 0;
    }
}

python版本

def intersection(s1, e1, s2, e2):
    # s2在 s1和e1 之间[s1, e1)。相交的部分就是
    if s1 <= s2 <e1: # 开始于s2,结束看e1 和 e2 的最小值。
        return min(e1, e2) - s2
    # s1在[s2, e2)之间
    if s2 <= s1 <e2:
        return min(e1, e2) - s1
    # 都满足不了
    return 0

def result():
    start = h1 * 60 + m1 # 把时间算出来
    except_end = min(h2*60+m2, 20 * 60) # 不能早于8点,不能晚于20点
    # 核酸点每检测一个人的时间花费是1分钟
    # 8点-10点每分钟增加3人, 出去1个人,相当于 8点~10点,每分钟增加2人
    # 其他时间每5分钟增加1人 出去1个人 10点~12点,相当于每分钟减少0.8人
    # 12点-14点每分钟增加10人,出去1个人 ,12~14点,相当于每分钟增加9人
    # 其他时间每5分钟增加1人 出去1个人 14~18点,相当于每分钟减少0.8人
    # 18点-20点每分钟增加20人 出去1个人 相当于18~20点,每分钟增加19人

    times = [
        [8 * 60, 10 * 60, 2],
        [10 * 60, 12 * 60, -0.8],
        [12 *60, 14 * 60, 9],
        [14 * 60, 18 * 60, -0.8],
        [18 * 60, 20 * 60, 19]
    ]
    def mapFn(target):
        # [核酸点id, 核酸点和张三的距离, 核酸点在张三出发时已有的人数]
        id, dis, wait = target
        arrived = start + dis * 10 # 每公里距离花费时间10分钟,费用是10元
        if arrived < 8*60: # 8点之前到
            arrived = 8*60 # 到达时间就是8点,排在初始人数后面。
            return [id,arrived-start+wait,dis *10]
        s1 = start # 算开始时间,
        e1 = arrived # 到达时间。然后取交集。在加上增速。
        for s2, e2, changePerMin in times:
            t = intersection(s1, e1, s2, e2)
            # 存在交叉的区间。
            if t > 0: # 重叠了多少区间,这个区间内按照比例增加。
                wait += t * changePerMin
                wait = max(0, wait) # 要注意,因为存在的人数减少的情况,所以要跟0取max
        return [id, arrived-start+int(wait), dis*10]
    ans = list(filter(lambda x: start+x[1]<=except_end, map(mapFn, targets))) # 非常棒啊。
    ans.sort(key=lambda x:(x[1], x[2], x[0])) # 不用判断ans>0?
    print(len(ans))
    for a in ans:
        print(" ".join(list(map(str, a))))
result()

参考链接:
1、知乎——python之map()函数
2、知乎——python之filter()函数
3、labuladong算法学习总结

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值