算法题——公司食堂

该博客介绍了一个关于食堂就餐规律的问题,男性优先选择已有1人的餐桌,女性则优先选择无人的餐桌。为避免遍历导致的时间过长,博主提出使用优先队列(二叉堆)的数据结构来优化解决方案,分别存储0人和1人餐桌的编号,并通过Java代码实现了这一算法,确保了在满足时间要求的情况下正确预测每个人会选择的餐桌。
摘要由CSDN通过智能技术生成

小美和小团所在公司的食堂有N张餐桌,从左到右摆成一排,每张餐桌有2张餐椅供至多2人用餐,公司职员排队进入食堂用餐。小美发现职员用餐的一个规律并告诉小团:当男职员进入食堂时,他会优先选择已经坐有1人的餐桌用餐,只有当每张餐桌要么空着要么坐满2人时,他才会考虑空着的餐桌;

当女职员进入食堂时,她会优先选择未坐人的餐桌用餐,只有当每张餐桌都坐有至少1人时,她才会考虑已经坐有1人的餐桌;

无论男女,当有多张餐桌供职员选择时,他会选择最靠左的餐桌用餐。现在食堂内已有若干人在用餐,另外M个人正排队进入食堂,小团会根据小美告诉他的规律预测排队的每个人分别会坐哪张餐桌。

输入描述:
第一行输入一个整数T(1<=T<=10),表示数据组数。

每组数据占四行,第一行输入一个整数N(1<=N<=500000);

第二行输入一个长度为N且仅包含数字0、1、2的字符串,第i个数字表示左起第i张餐桌已坐有的用餐人数;

第三行输入一个整数M(1<=M<=2N且保证排队的每个人进入食堂时都有可供选择的餐桌);

第四行输入一个长度为M且仅包含字母M、F的字符串,若第i个字母为M,则排在第i的人为男性,否则其为女性。

输出描述:
每组数据输出占M行,第i行输出一个整数j(1<=j<=N),表示排在第i的人将选择左起第j张餐桌用餐。

输入例子1:
1
5
01102
6
MFMMFF

输出例子1:
2

//本题逻辑很简单,但是由于有时间要求,如果用普通的for遍历来实现,会导致超时,用sout的方式的会造成时间增加,
//所以需要用BufferedReader和BufferedWriter来进行读写操作
public class Test03 {
    public static void main(String[] args) throws IOException {
        BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
        BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(System.out));
        int T = Integer.parseInt(reader.readLine());
        for (int i0 = 0; i0 < T; i0++) {
            int N = Integer.parseInt(reader.readLine());
            char[] a = reader.readLine().toCharArray();
            int M = Integer.parseInt(reader.readLine());
            char[] b = reader.readLine().toCharArray();
            //创建一个对象为优先队列的集合,集合0是0人桌队列,集合1是1人桌队列
            //优先队列数据结构为二叉堆(默认小顶堆,大顶堆需要添加逆序比较器Collections.reverseOrder)
            List<PriorityQueue<Integer>> queueList = new ArrayList<>();
            queueList.add(new PriorityQueue<>());
            queueList.add(new PriorityQueue<>());
            for (int i = 0; i < N; i++) {
                if (a[i] - '0' < 2) {
                    //不同人桌的队列里放从小到大的桌号
                    queueList.get(a[i] - '0').offer(i + 1);
                }
            }
            int x;
            for (int i = 0; i < M; i++) {
                if (b[i] == 'M') {
                    //找1人桌的桌子,假如不为空
                    if (!queueList.get(1).isEmpty()) {
                        //找到1人桌的桌子,输出桌号并出堆
                        x = queueList.get(1).poll();
                        writer.write(String.valueOf(x));
                        writer.newLine();
                    } else {
                        //找到0人桌的桌子,输出桌号并出堆
                        x = queueList.get(0).poll();
                        //将出堆的0人桌插入到1人桌的队列
                        queueList.get(1).offer(x);
                        writer.write(String.valueOf(x));
                        writer.newLine();
                    }

                } else {
                    if (!queueList.get(0).isEmpty()) {
                        x = queueList.get(0).poll();
                        queueList.get(1).offer(x);
                        writer.write(String.valueOf(x));
                        writer.newLine();
                    } else {
                        x = queueList.get(1).poll();
                        writer.write(String.valueOf(x));
                        writer.newLine();
                    }
                }

            }
            writer.flush();
        }
    }
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值