算法竞赛入门经典 习题5-16

UVa212

Use of Hospital Facilities

医院包含手术室和恢复室两种类型的房间,病人需要先在手术室进行手术,然后转移到恢复室中恢复,病人只可能在由于手术室不足而等待,而不回因为恢复室不足而等待。给定每个病人的手术时间和恢复时间,模拟医院的业务流程,并打印每个手术室和每个恢复室的统计信息。

借鉴习题5-13的思路,在每个会发生事件的时间点对病人、手术室和恢复室进行调度即可。这里首先定义可能发生的事件类型,在本题中只需要定义手术室可用事件和ROOM_READYROOM_FINISHED两种即可,因为题目保证了病人不会因恢复室不足而等待,因此当手术完成后,可以直接将病人转移到可用的编号最小的恢复室中,同时由于病人恢复所用时间是已知的,因此恢复室再次可用的事件也是可以算出来的。定义了事件的类型后,只需要根据题目要求模拟即可。

这道题提交后RTE后的好多次,是因为最开始是在VSCode上用g++编译的,Patient类的输入运算符没有返回标准输入流,而g++没有报错,提交后就一直报错,还以为是数组越界了。

还有一个坑就是病人的数量可能为0,这时统计病房信息的分母就可能为0,需要特殊处理。

最后,输出格式题目中没有特别说明,因此在代码的最后给出了正确输出的样例。

#include 
#include 
#include 
#include 
#include 

using namespace std;

enum class EventType
{
	ROOM_READY,
	ROOM_FINISHED,
};

struct Event
{
	EventType et;
	int minute;
	Event(EventType type, int minute) : et(type), minute(minute) {};
	bool operator<(const Event &e) const
	{
		if (minute < e.minute) return true;
		else if (minute == e.minute) {
			if (et != e.et && et == EventType::ROOM_READY) return true;
			else return false;
		}
		else return false;
	}
};

struct Room
{
	int no;
	int StartingTime, UsedTime;
	size_t PatientIndex;
	int AvailableTime, EndTime;
	Room(int no, int StartingTime) : no(no), StartingTime(StartingTime),
		UsedTime(0), AvailableTime(0), EndTime(0) {};
};

struct Patient
{
	string name;
	int SurgeyTime, RecoveryTime;
	size_t RoomNo, BedNo;
	int SurgeryStartingTime, SurgeryEndTime;
	int RecoveryStartingTime, RecoveryEndTime;
	Patient()
	{
		RoomNo = 0, BedNo = 0;
		SurgeryStartingTime = 0, SurgeryEndTime = 0;
		RecoveryStartingTime = 0, RecoveryEndTime = 0;
	}
};

istream& operator >> (istream &is, Patient &patient)
{
	is >> patient.name >> patient.SurgeyTime >> patient.RecoveryTime;
	return is;
}

void ProcessRoomReady(set<Event> &events, vector<Room> &rooms, vector<Room> &beds, vector<Patient> &patients, size_t &PatientIndex, int current)
{
	for (Room &room : rooms)
	{
		if (room.AvailableTime == current) {
			if (room.StartingTime == -1) {
				room.StartingTime = current;
			}
			room.UsedTime += patients[PatientIndex].SurgeyTime;
			room.PatientIndex = PatientIndex;
			room.EndTime = current + patients[PatientIndex].SurgeyTime;
			patients[PatientIndex].RoomNo = room.no;
			patients[PatientIndex].SurgeryStartingTime = current;
			patients[PatientIndex].SurgeryEndTime = patients[PatientIndex].SurgeryStartingTime + patients[PatientIndex].SurgeyTime;
			events.insert(Event(EventType::ROOM_FINISHED, room.EndTime));
			PatientIndex++;
			if (PatientIndex == patients.size()) {
				break;
			}
		}
	}
}

void ProcessRoomFinished(set<Event> &events, vector<Room> &rooms, vector<Room> &beds, vector<Patient> &patients,
	int current, int O2RTime, int PrepareRoom, int PrepareBed)
{
	for (Room &room : rooms)
	{
		if (room.EndTime == current) {
			room.AvailableTime = current + PrepareRoom;
			events.insert(Event(EventType::ROOM_READY, room.AvailableTime));
			for (Room &bed : beds)
			{
				if (bed.AvailableTime <= current) {
					if (bed.StartingTime == 0) {
						bed.StartingTime = current + O2RTime;
					}
					bed.UsedTime += patients[room.PatientIndex].RecoveryTime;
					bed.PatientIndex = room.PatientIndex;
					bed.EndTime = current + O2RTime + patients[room.PatientIndex].RecoveryTime;
					bed.AvailableTime = bed.EndTime + PrepareBed;
					patients[room.PatientIndex].BedNo = bed.no;
					patients[room.PatientIndex].RecoveryStartingTime = current + O2RTime;
					patients[room.PatientIndex].RecoveryEndTime = patients[room.PatientIndex].RecoveryStartingTime + patients[room.PatientIndex].RecoveryTime;
					break;
				}
			}
		}
	}
}

void PrintPatient(const vector<Patient> &patients, int StartingHour)
{
	cout << " Patient          Operating Room          Recovery Room" << endl;
	cout << " #  Name     Room#  Begin   End      Bed#  Begin    End" << endl;
	cout << " ------------------------------------------------------" << endl;
	for (size_t i = 0; i < patients.size(); i++)
	{
		cout << setw(2) << setfill(' ') << i + 1 << "  ";
		cout << patients[i].name << string(9 - patients[i].name.length(), ' ') << ' ';
		cout << setw(2) << patients[i].RoomNo << "   ";
		cout << setw(2) << setfill(' ') << StartingHour + patients[i].SurgeryStartingTime / 60 << ':' << setw(2) << setfill('0') << patients[i].SurgeryStartingTime % 60 << "   ";
		cout << setw(2) << setfill(' ') << StartingHour + patients[i].SurgeryEndTime / 60 << ':' << setw(2) << setfill('0') << patients[i].SurgeryEndTime % 60 << "     ";
		cout << setw(2) << setfill(' ') << patients[i].BedNo << "   ";
		cout << setw(2) << setfill(' ') << StartingHour + patients[i].RecoveryStartingTime / 60 << ':' << setw(2) << setfill('0') << patients[i].RecoveryStartingTime % 60 << "   ";
		cout << setw(2) << setfill(' ') << StartingHour + patients[i].RecoveryEndTime / 60 << ':' << setw(2) << setfill('0') << patients[i].RecoveryEndTime % 60;
		cout << endl;
	}
	cout << endl;
}

void PrintRoomAndBed(const vector<Patient> &patients, const vector<Room> &rooms, const vector<Room> &beds)
{
	int LastLeaveBed = 0;
	for (const Patient &patient : patients)
	{
		if (patient.RecoveryEndTime > LastLeaveBed) {
			LastLeaveBed = patient.RecoveryEndTime;
		}
	}
	cout << "Facility Utilization" << endl;
	cout << "Type  # Minutes  % Used" << endl;
	cout << "-------------------------" << endl;
	for (size_t i = 0; i < rooms.size(); i++)
	{
		cout << "Room " << setw(2) << setfill(' ') << i + 1 << "    " << setw(4) << rooms[i].UsedTime << "  ";
		cout << fixed << setw(6) << setfill(' ') << setprecision(2);
		if (LastLeaveBed == 0) cout << 0.0 << endl;
		else cout << 100.0 * rooms[i].UsedTime / LastLeaveBed << endl;
	}
	for (size_t i = 0; i < beds.size(); i++)
	{
		cout << "Bed  " << setw(2) << setfill(' ') << i + 1 << "    " << setw(4) << beds[i].UsedTime << "  ";
		cout << fixed << setw(6) << setfill(' ') << setprecision(2);
		if (LastLeaveBed == 0) cout << 0.0 << endl;
		else cout << 100.0 * beds[i].UsedTime / LastLeaveBed << endl;
	}
	cout << endl;
}

void simiulation(vector<Room> &rooms, vector<Room> &beds, vector<Patient> &patients,
	int StartingHour, int O2RTime, int PrepareRoom, int PrepareBed)
{
	set<Event> events;
	events.insert(Event(EventType::ROOM_READY, 0));
	size_t PatientIndex = 0;
	while (!events.empty()) {
		const Event &event = *events.begin();
		switch (event.et)
		{
		case EventType::ROOM_READY:
			if (PatientIndex == patients.size()) {
				break;
			}
			ProcessRoomReady(events, rooms, beds, patients, PatientIndex, event.minute);
			break;
		case EventType::ROOM_FINISHED:
			ProcessRoomFinished(events, rooms, beds, patients, event.minute, O2RTime, PrepareRoom, PrepareBed);
			break;
		default:
			break;
		}
		events.erase(events.begin());
	}
	PrintPatient(patients, StartingHour);
	PrintRoomAndBed(patients, rooms, beds);
}

int main()
{
	int RoomNum, BedNum, StartingHour, O2RTime, PrepareRoom, PrepareBed, PatientNum;
	while (cin >> RoomNum) {
		cin >> BedNum >> StartingHour >> O2RTime >> PrepareRoom >> PrepareBed >> PatientNum;
		vector<Patient> patients;
		for (int i = 0; i < PatientNum; i++)
		{
			Patient patient;
			cin >> patient;
			patients.push_back(patient);
		}
		vector<Room> rooms, beds;
		for (int i = 0; i < RoomNum; i++)
		{
			rooms.push_back(Room(i + 1, -1));
		}
		for (int i = 0; i < BedNum; i++)
		{
			beds.push_back(Room(i + 1, 0));
		}
		simiulation(rooms, beds, patients, StartingHour, O2RTime, PrepareRoom, PrepareBed);
	}
	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

 Patient          Operating Room          Recovery Room
 #  Name     Room#  Begin   End      Bed#  Begin    End
 ------------------------------------------------------
 1  Jones      1    7:00    7:28      3    7:33    9:53
 2  Smith      2    7:00    9:00      1    9:05   12:25
 3  Thompson   3    7:00    7:23      2    7:28    8:43
 4  Albright   4    7:00    7:19      1    7:24    8:46
 5  Poucher    5    7:00    9:13      5    9:18   12:47
 6  Comer      4    7:34    8:48      4    8:53   10:34
 7  Perry      3    7:38    9:11      2    9:16   12:24
 8  Page       1    7:43    9:34      6    9:39   13:22
 9  Roggio     4    9:03   10:12      9   10:17   12:19
10  Brigham    2    9:15    9:57      8   10:02   11:21
11  Nute       3    9:26    9:48      7    9:53   11:04
12  Young      5    9:28   10:06      3   10:11   12:31
13  Bush       1    9:49   10:15     10   10:20   12:21
14  Cates      3   10:03   12:03      8   12:08   16:16
15  Johnson    2   10:12   11:38      4   11:43   14:44
16  White      5   10:21   11:53      7   11:58   14:18

Facility Utilization
Type  # Minutes  % Used
-------------------------
Room  1     165   29.68
Room  2     248   44.60
Room  3     258   46.40
Room  4     162   29.14
Room  5     263   47.30
Bed   1     282   50.72
Bed   2     263   47.30
Bed   3     280   50.36
Bed   4     282   50.72
Bed   5     209   37.59
Bed   6     223   40.11
Bed   7     211   37.95
Bed   8     327   58.81
Bed   9     122   21.94
Bed  10     121   21.76
Bed  11       0    0.00
Bed  12       0    0.00


*/

你可能感兴趣的:(《算法竞赛入门经典》,算法)