UVA ~ 212 ~ Use of Hospital Facilities (优先队列+模拟)

题意:医院里有n (n<10) ↑手术室和m (m<30) 个恢复室。每个病人首先会被分配时一个手术室,手术后会被分配到一个恢复室。从任意手术室到任意恢复室的时间均为t1,准备个手术室和恢复室的时间分别为t2和t3(一开始所有手术室和恢复室均准备好,只有接持完一个病人之后才需要为下一个病人准备)。

    k 名(k<=100) 病人按照花名册顺序排队,T点钟准时开放手术室。每当有准备好的手术室时,队首病人进入其中编号最小的手术室。手术结束后,病人应立刻进入编号最小恢复室。如果有多个病人同时结束手术,在编号较小的手术室做手术的病人优先进入编号较小的恢复室。输入保证病人无须排队等待恢复室。

    输入n,m,T,t1,t2,t3,k和k名病人的名字、手术时间和恢复时间,模拟这个过程,输入输出细节请参考原题。

提示:虽然是个模拟题,但是最好先理清思路,减少不必要的麻烦。本题是一个很好的编程练习,但难度也不小。

以上内容来自算法入门经典。

补充:先按病人花名册顺序输出,每个人的编号,名字,手术室编号,手术开始和结束时间,恢复室编号,恢复开始和结束时间,然后输出,每个手术室(Room)和恢复室(Bed)的使用时间和使用率。使用率为,房间使用时间*100.0/总时间。总时间是第一个手术开始到最后一个病人离开恢复室。


思路:自己想不清楚,只能想出来手术室怎么处理,死活想不出来恢复室安排怎么算,怎么保存。只能去看别人怎么写的。。。

RoomUse[i]保存第i手术室的使用时间,BedUse[i]保存第i个恢复室的使用时间。patient[i]保存第i个病人的信息。

我们用一个优先队列保存所有的手术室,优先按手术室可以开始下一次手术的时间排序,然后按照手术室ID排序。每次取出队首的手术室,让病人去这个手术室手术,然后计算出来该病人的手术和恢复的开始和结束时间,保存手术室编号,手术室的使用时间增加。

然后计算恢复室的信息,开一个数组Bre,Bre[j]表示第j个恢复室可以接待下一个病人的时间。双重for,外层遍历每个病人,内层遍历m个恢复室,当病人的手术结束时间在Bre[j]之间,即可以取j号恢复室恢复,那么安排这个人去j恢复室,更新Bre[j],保存该病人的恢复室编号,j恢复室使用时间增加。

过程中维护一个Te表示最后一个病人离开恢复室的时间,即结束时间。

然后按要求输出即可。


#include<bits/stdc++.h>
using namespace std;
const int MAXN = 105;
struct Patient//病人
{
    char name[105];
    int t1, t2;//手术时间,恢复时间
    int id, RoomID, BedID;//编号,手术室编号,恢复床id
    int Start1, End1;//手术开始时间,结束时间
    int Start2, End2;//恢复开始时间,结束时间
};
struct Room//手术室
{
    int Start, id;//下一次可以接手术的时间,手术室id
    Room (int _Start, int _id): Start(_Start), id(_id) {}
    bool operator < (const Room& that) const
    {
        if (Start != that.Start) return that.Start < Start;
        return that.id < id;
    }
};
int main()
{
    int n, m, T, t1, t2, t3, k;
    while(~scanf("%d%d%d%d%d%d%d", &n, &m, &T, &t1, &t2, &t3, &k))
    {
        vector<Patient> patient(k);//k个病人
        priority_queue<Room> PQ;
        vector<int> RoomUse(n + 1, 0);//手术室使用时间
        for (int i = 1; i <= n; i++)
            PQ.push(Room(T*60, i));
        for (int i = 0; i < k; i++)
        {
            auto& now(patient[i]);
            scanf("%s%d%d", now.name, &now.t1, &now.t2);
            now.id = i + 1;//病人编号
            Room u = PQ.top(); PQ.pop();
            now.Start1 = u.Start;//开始手术时间
            now.End1 = now.Start1 + now.t1;//结束手术时间
            now.Start2 = now.End1 + t1;//开始恢复时间
            now.End2 = now.Start2 + now.t2;//结束恢复时间
            now.RoomID = u.id;//该病人的手术室id
            RoomUse[u.id] += now.t1;//u.id手术室使用时间增加
            PQ.push(Room(now.End1 + t2, u.id));
        }
        //按手术结束时间早的排序,相同按手术室编号小的排序
        sort(patient.begin(), patient.end(), [](Patient& a, Patient& b)->bool
             { if (a.End1 != b.End1) return a.End1 < b.End1; return a.RoomID < b.RoomID; } );

        int Te = 0;//维护结束时间
        vector<int> Bre(m + 1, T*60);//恢复室开始时间
        vector<int> BedUse(m + 1, 0);//恢复室使用时间
        for (int i = 0; i < k; i++)
        {
            auto& now(patient[i]);
            int j;
            for (j = 1; j <= m; j++)
                if (Bre[j] <= now.End1) break;
            now.BedID = j;//该病人的恢复室id
            Bre[j] = now.End2 + t3;//结束恢复时间+恢复室准备时间
            BedUse[j] += now.t2;//j恢复室使用时间增加
            Te = max(Te, now.End2);//维护结束时间
        }
        //按病人编号排序
        sort(patient.begin(), patient.end(), [](Patient& a, Patient& b) { return a.id < b.id; });
        puts(" Patient          Operating Room          Recovery Room");
        puts(" #  Name     Room#  Begin   End      Bed#  Begin    End");
        puts(" ------------------------------------------------------");
        for(int i = 0; i < k; i++)
        {
            auto& now(patient[i]);
            printf("%2d  %-9s ", now.id, now.name);
            printf("%2d  %3d:%02d  %3d:%02d     ", now.RoomID, now.Start1/60, now.Start1%60, now.End1/60, now.End1%60);
            printf("%2d  %3d:%02d  %3d:%02d\n", now.BedID, now.Start2/60, now.Start2%60, now.End2/60, now.End2%60);
        }printf("\n");
        puts("Facility Utilization");
        puts("Type  # Minutes  % Used");
        puts("-------------------------");
        for(int i = 1; i <= n; i++) printf("Room %2d %7d %7.2f\n", i, RoomUse[i], RoomUse[i] * 100.0 / (Te - T*60));
        for(int i = 1; i <= m; i++) printf("Bed  %2d %7d %7.2f\n", i, BedUse[i], BedUse[i] * 100.0 / (Te - T*60));
        printf("\n");
    }
    return 0;
}
/*
5 12 07 5 15 10 16
Jones
28 140
Smith
120 200
Thompson
23 75
Albright
19 82
Poucher
133 209
Comer
74 101
Perry
93 188
Page
111 223
Roggio
69 122
Brigham
42 79
Nute
22 71
Young
38 140
Bush
26 121
Cates
120 248
Johnson
86 181
White
92 140
*/


  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值