2021/3/29算法题打卡-外卖优先级

外卖店优先级

题目

外卖店优先级
时间限制: 1.0s 内存限制: 512.0MB 本题总分:20 分
【问题描述】
“饱了么”外卖系统中维护着 N 家外卖店,编号 1 ∼ N。每家外卖店都有 一个优先级,初始时 (0 时刻) 优先级都为 0。
每经过 1 个时间单位,如果外卖店没有订单,则优先级会减少 1,最低减 到 0;而如果外卖店有订单,则优先级不减反加,每有一单优先级加 2。
如果某家外卖店某时刻优先级大于 5,则会被系统加入优先缓存中;如果 优先级小于等于 3,则会被清除出优先缓存。
给定 T 时刻以内的 M 条订单信息,请你计算 T 时刻时有多少外卖店在优 先缓存中。
【输入格式】 第一行包含 3 个整数 N、M 和 T。 以下 M 行每行包含两个整数 ts 和 id,表示 ts 时刻编号 id 的外卖店收到 一个订单。
【输出格式】
输出一个整数代表答案。
【样例输入】 2 6 6
1 1
5 2
3 1
6 2
2 1
6 2

【样例输出】 1
【样例解释】 6 时刻时,1 号店优先级降到 3,被移除出优先缓存;2 号店优先级升到 6, 加入优先缓存。所以是有 1 家店 (2 号) 在优先缓存中。
【评测用例规模与约定】 对于 80% 的评测用例,1≤ N,M,T ≤10000。 对于所有评测用例,1≤ N,M,T ≤100000,1≤ts≤T,1≤id ≤ N。

解析

模拟
先存下每个时刻的所有订单,然后计算出每个店铺,每个时刻的优先级,然后根据这个优先级表得到最后的结果
当最后T时刻的优先级大于5,则一定在优先缓存中,T时刻优先级小于等于3则一定不在优先缓存中,而当最后一个大于6的位置到最后T时刻之间出现了一个小于等于3的优先级,则一定不在优先缓存中,否则在优先缓存中

代码

package com.blueBrageCup.B2019;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.*;

/**
 * @auther thk
 * @date 2021/3/29 - 10:44
 */
/*
public class T7外卖优先级 {

    static List<Map<Integer,Integer>> list = new ArrayList<>(); //所以店铺的每个时刻的优先级
    static Map<Integer,List<Integer>> map = new HashMap<>();    //每个时刻的订单数
    static int N;   //店铺
    static int M;   //订单
    static int T;   //总时间



    //初始化
    private static void init() {
        for(int i=0;i<T;i++){
            List<Integer> list = new ArrayList<>();
            map.put(i+1,list);
        }

        for(int i=0;i<N;i++){
            Map<Integer,Integer> map = new HashMap<>();
            list.add(map);
        }
    }

    public static void main(String[] args) throws IOException {
        BufferedReader bf = new BufferedReader(new InputStreamReader(System.in));
        String[] s = bf.readLine().split(" ");
        N=Integer.parseInt(s[0]);
        M=Integer.parseInt(s[1]);
        T=Integer.parseInt(s[2]);

        init();

        //装入每个时刻的订单数据
        for(int i=0;i<M;i++){
            String[] s1 = bf.readLine().split(" ");
            int b = Integer.parseInt(s1[0]);    //时刻
            int o = Integer.parseInt(s1[1]);    //店铺id

            List<Integer> list = map.get(b);
            list.add(o);
            map.put(b,list);
        }

        //取出每个时刻的所以订单
        Set<Integer> set = map.keySet();
        for(int j=1;j<=T;j++){
            for(Map<Integer,Integer> map:list){
                map.put(j,0);
            }
        }

        //得到每个店铺,每个时间的优先级
        for(int j:set){ //j是时刻
            List<Integer> list2 = map.get(j);  //list2是每个时刻的所有订单
            List<Integer> index = new ArrayList<>();
            for(int k=0;k<N;k++) {             //每个店铺都有一个自己的下标
                index.add(j - 1);              //优先级在第一时刻是按照0+2,后面的时刻再而三按照前一个时刻加或减的,index就是当下要按照加减的下标
            }
            for(int k:list2) {                 //加的情况
                for(int i=1;i<=N;i++){
                    if(k==i && j==1){          //第一个时刻按照0+2
                        list.get(i-1).put(j,2);
                    }else if(k==i) {
                        list.get(i - 1).put(j, list.get(i - 1).get(index.get(i-1)) + 2);
                        if(index.get(i-1)!=j)                   //按照前面的加过一次后,后面应该按照的自己本身来加了
                            index.set(i-1,index.get(i-1)+1);
                    }
                }

            }
            for(int i=1;i<=N;i++)              //减少的情况
                if(!list2.contains(i)){        //不包含本店铺就减少1
                    if(j==1)                   //第一个时刻不减少
                        list.get(i-1).put(j,0);
                    else                       //按照前一个来减少,因为只可能减少一次,所以不用判断下标是否+1
                        list.get(i-1).put(j,list.get(i-1).get(j-1)==0?0:list.get(i-1).get(j-1)-1);
                }
        }

        int count=0;

        for(int i=0;i<N;i++){
            Integer integer = list.get(i).get(T);
            if(integer>5) {                    //如果最后一个都大于5则一定在优先中
                count++;
                continue;
            }
            if(integer<=3)                     //如果最后一个小于等于3则一定被清除出优先区
                continue;
            if(!list.get(i).containsValue(6))  //如果从未大于6过则一定是不在优先区的
                continue;
            else{                              //如果最后一个大于三则可能是前面大于6后减少到的,这是仍然在优先区中
                int index=0;
                Set<Integer> set1 = list.get(i).keySet();
                for(int j:set1){
                    if(list.get(i).get(j)>=6)
                        index=j;               //找到最后一个大于6的位置
                }

                int flag=1;
                for(int j=index;j<=T;j++){  //从最后一个大于6的时间节点,如何后面出现了某时刻小于3则最后一定不可能在优先区
                    if(list.get(i).get(j)<=3){
                        flag=0;
                        break;
                    }
                }

                if(flag==1)
                    count++;
            }
        }

        System.out.println(count);
    }

}

posted @ 2021-03-29 15:42  唐坣  阅读(172)  评论(0)    收藏  举报