pat甲级1026(30分)c++

本文探讨了一种高效的服务分配算法,旨在解决桌游馆中VIP顾客和普通顾客在有限桌子资源下的公平服务问题。通过详细解析代码,我们了解了如何根据不同顾客类型和桌子类型进行智能分配,确保每位顾客得到及时的服务。
摘要由CSDN通过智能技术生成

pat甲级1026(30分)c++

#include <iostream>
#include <vector>
#include <algorithm>
#include <cmath>
using namespace std;

/*
 * 题目大意:
 * 输入:
 * 第一行:
 * N是成员的数量
 * 接下来N行:
 * 每一行包含成员的到达时间,成员使用时间(以分钟为单位),以及是否为vip
 * 接下来一行:K是桌子的总数,M是vip桌子数量
 * 接下来:M个数(1到k之间),vip桌子的编号
 * 输出:
 * 到达时间,服务时间,等待时间(分钟为单位),前提是到达时间在关门之前可以被服务
 * 每个桌子服务的数量
 * 注:
 * 1、vip桌子是在等待队列中没有vip成员且非vip桌子已经用尽的情况之下才分配给非vip成员
 * 2、当vip成员在等待队列时,需要判断vip桌子是否有剩余,如果有,则vip成员无需等待,直接使用vip桌子;如果没有,则vip成员仍然需要等待空桌子或vip桌子
 */

/*
 * 成员的结构体
 * arrive为到达时间,start为开始时间,time为等待时间,vip标识是否为vip成员
 */
struct person {
    int arrive, start, time;
    bool vip;
}tempperson;

/*
 * 桌子的结构体
 * end为结束使用时间,num为使用过的成员数,vip标识是否为vip桌子
 */
struct tablenode {
    int end = 8 * 3600, num;
    bool vip;
};

/*
 * 以到达时间递增排序
 */
bool cmp1(person a, person b) {
    return a.arrive < b.arrive;
}

/*
 * 以开始时间递增排序
 */
bool cmp2(person a, person b) {
    return a.start < b.start;
}

//分别存放成员和桌子
vector<person> player;
vector<tablenode> table;
/*
 * 为成员分配桌子,更新对应的成员和桌子属性
 */
void alloctable(int personid, int tableid) {
    if(player[personid].arrive <= table[tableid].end)
        player[personid].start = table[tableid].end;
    else
        player[personid].start = player[personid].arrive;
    table[tableid].end = player[personid].start + player[personid].time;
    table[tableid].num++;
}
/*
 * 找到下一个vip会员的索引
 */
int findnextvip(int vipid) {
    vipid++;
    while(vipid < player.size() && player[vipid].vip == false) vipid++;
    return vipid;
}
int main() {
    //初始化
    int n, k, m, viptable;
    scanf("%d", &n);
    for(int i = 0; i < n; i++) {
        int h, m, s, temptime, flag;
        scanf("%d:%d:%d %d %d", &h, &m, &s, &temptime, &flag);
        tempperson.arrive = h * 3600 + m * 60 + s;
        tempperson.start = 21 * 3600;
        //到达时间超过21:00的无需加入队列
        if(tempperson.arrive >= 21 * 3600) continue;
        tempperson.time = temptime <= 120 ? temptime * 60 : 7200;
        tempperson.vip = ((flag == 1) ? true : false);
        player.push_back(tempperson);
    }
    scanf("%d%d", &k, &m);
    table.resize(k + 1);
    for(int i = 0; i < m; i++) {
        scanf("%d", &viptable);
        table[viptable].vip = true;
    }
    //按到达时间排序player
    sort(player.begin(), player.end(), cmp1);
    //i是用户编号,vipid是下一个vip用户编号
    int i = 0, vipid = -1;
    //找到第一个vip成员
    vipid = findnextvip(vipid);
    while(i < player.size()) {
        //index为最早空闲的桌子编号,minendtime为最早空闲的时间
        int index = -1, minendtime = 999999999;
        //更新index和minendtime
        for(int j = 1; j <= k; j++) {
            if(table[j].end < minendtime) {
                minendtime = table[j].end;
                index = j;
            }
        }
        //如果最早空闲的桌子结束时间超过21:00.退出循环
        if(table[index].end >= 21 * 3600) break;
        //判断是否为下一位vip成员,不是则跳过,主要是判断vip用户是否已经分配过桌子
        if(player[i].vip == true && i < vipid) {
            i++;
            continue;
        }
        //判断是否轮到vip桌子
        if(table[index].vip == true) {//是vip桌子
            //判断是否当前为vip用户
            if(player[i].vip == true) {//是vip成员
                //为vip用户分配vip桌子
                alloctable(i, index);
                //找到下一个vip成员
                if(vipid == i) vipid = findnextvip(vipid);
                i++;
            } else {//不是vip成员
                //判断下一个vip成员是否已经在等待
                if(vipid < player.size()
                && player[vipid].arrive <= table[index].end) {//已经在等待
                    //为下一个vip成员分配vip桌子
                    alloctable(vipid, index);
                    vipid = findnextvip(vipid);
                } else {//没有到来
                    //为非vip成员分配vip桌子
                    alloctable(i, index);
                    i++;
                }
            }
        } else {//不为vip桌子
            //判断是否为vip成员
            if(player[i].vip == false) {//非vip成员
                //直接分配非vip桌子
                alloctable(i, index);
                i++;
            } else {//vip成员
                //vipindex为最早空闲的vip桌子,minvipendtime为最早空闲的vip桌子结束时间
                int vipindex = -1, minvipendtime = 999999999;
                for(int j = 1; j <= k; j++) {
                    if(table[j].vip == true && table[j].end < minvipendtime) {
                        minvipendtime = table[j].end;
                        vipindex = j;
                    }
                }
                //判断vip桌子是否有空闲
                if(vipindex != -1 && player[i].arrive >= table[vipindex].end) {//有空闲
                    alloctable(i, vipindex);
                    if(vipid == i) vipid = findnextvip(vipid);
                    i++;
                } else {//无空闲
                    //分配非vip桌子
                    alloctable(i, index);
                    if(vipid == i) vipid = findnextvip(vipid);
                    i++;
                }
            }
        }
    }
    //根据开始时间将player递增排列
    sort(player.begin(), player.end(), cmp2);
    //格式化输出
    for(i = 0; i < player.size() && player[i].start < 21 * 3600; i++) {
        printf("%02d:%02d:%02d ", player[i].arrive / 3600, player[i].arrive %
                                                           3600 / 60, player[i].arrive % 60);
        printf("%02d:%02d:%02d ", player[i].start / 3600, player[i].start %
                                                          3600 / 60, player[i].start % 60);
        printf("%.0f\n", round((player[i].start - player[i].arrive) / 60.0));
    }
    for(int i = 1; i <= k; i++) {
        if(i != 1) printf(" ");
        printf("%d", table[i].num);
    }
    return 0;
}

这道题还是存在不太懂的地方,难点在于处理vip成员和vip桌子的分配关系,思路是遍历用户,当用户为非vip用户,判断遇到的桌子是否为vip桌子,不是则直接分配,是vip桌子则需要判断最早到达的vip用户是否已经到达,如果已经到达,则分配给vip用户一个vip桌子,继续判断最早空闲桌子以及最早到达的vip成员,如果没有到达,则分配给非vip用户一个vip桌子;如果是vip用户,则需要判断有无空闲vip桌子,有空闲的vip桌子则直接分配,如果没有则分配非vip桌子。
总而言之,这道题主要考察对于题目的分析和条件的判断,很绕,具体请看代码,理清楚先后顺序之后会很简单

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值