import java.io.; import java.util.;
interface Printer { void p(Object... o);
void pn(Object... o);
default String format(Object... o) {
String format;
if (o.length == 1) {
format = o[0].toString();
} else {
Object[] dest = new Object[o.length - 1];
System.arraycopy(o, 1, dest, 0, dest.length);
format = String.format(o[0].toString(), dest);
}
return format;
}
}
class MyPrinter implements Printer { @Override public void p(Object... o) { printToFile(false, o); System.out.print(format(o)); }
@Override
public void pn(Object... o) {
printToFile(true, o);
if (o == null || o.length == 0) {
System.out.println();
} else {
System.out.println(format(o));
}
}
private void printToFile(boolean nl, Object... o) {
if (writer == null) {
return;
}
try {
if (o.length != 0) {
writer.write(format(o));
}
if (nl) {
writer.write("\n");
}
writer.flush();
} catch (IOException e) {
e.printStackTrace();
}
}
private static FileWriter writer;
static {
if ("true".equals(System.getenv("OUTPUT_TO_LOCAL"))) {
try {
writer = new FileWriter("D:\\output.txt");
writer.write("");
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
public class Main {
public static void main(String[] args) {
solution(System.in, new MyPrinter());
}
public static void solution(InputStream in, Printer p) {
Scanner scanner = new Scanner(in);
while (scanner.hasNextLine()) {
// Number of operating rooms (maximum of 10)
// Number of recovery room beds (maximum of 30)
// Starting hour for 1st surgery of day (based on a 24-hour clock)
// Minutes to transport patient from operating room to recovery room
// Minutes to prepare operating room for next patient
// Minutes to prepare recovery room bed for next patient
// Number of surgery patients for the day (maximum of 100)
int opRoomCount = scanner.nextInt();
int rcRoomCount = scanner.nextInt();
int startHour = scanner.nextInt();
int mFromOpToRc = scanner.nextInt();
int mPreOpRoom = scanner.nextInt();
int mPreRcRoom = scanner.nextInt();
int patientCount = scanner.nextInt();
scanner.nextLine();
LinkedList<Patient> psOp = new LinkedList<>();
ArrayList<Patient> ps = new ArrayList<>();
HashMap<Integer, Patient> idPatientMap = new HashMap<>();
for (int i = 0; i < patientCount; i++) {
String name = scanner.nextLine();
int opTime = scanner.nextInt();
int rcTime = scanner.nextInt();
Patient patient = new Patient(i, name, opTime, rcTime);
psOp.add(patient);
ps.add(patient);
idPatientMap.put(i, patient);
scanner.nextLine();
}
PriorityQueue<Event> events = new PriorityQueue<>();
TreeSet<Integer> availableOpRoom = new TreeSet<>();
TreeMap<Integer, Integer> opRecord = new TreeMap<>();
TreeMap<Integer, Integer> rcRecord = new TreeMap<>();
for (int i = 0; i < opRoomCount; i++) {
availableOpRoom.add(i);
events.add(new Event(Event.EVENT_OP_FREE, i, 0, -1));
}
TreeSet<Integer> availableRcRoom = new TreeSet<>();
for (int i = 0; i < rcRoomCount; i++) {
availableRcRoom.add(i);
events.add(new Event(Event.EVENT_RC_FREE, i, 0, -1));
}
int currentTimeMin = 0;
while (!events.isEmpty()) {
Event event = events.poll();
currentTimeMin = event.happenTime;
switch (event.type) {
case Event.EVENT_OP_FREE:
// put patient to rc room
if (event.patientId >= 0) {
Patient patient = idPatientMap.get(event.patientId);
patient.rcRoom = availableRcRoom.pollFirst();
patient.rcStTime = currentTimeMin + mFromOpToRc;
patient.rcEdTime = patient.rcStTime + patient.rcTime;
events.add(new Event(Event.EVENT_RC_FREE, patient.rcRoom, patient.rcEdTime + mPreRcRoom, patient.id));
rcRecord.put(patient.rcRoom, rcRecord.computeIfAbsent(patient.rcRoom, it -> 0) + patient.rcTime);
}
// put another patient to op room
availableOpRoom.add(event.roomId);
if (!psOp.isEmpty()) {
Patient patient = psOp.pop();
patient.opRoom = availableOpRoom.pollFirst();
patient.opStTime = event.patientId < 0 ? currentTimeMin : currentTimeMin + mPreOpRoom;
patient.opEdTime = patient.opStTime + patient.opTime;
events.add(new Event(Event.EVENT_OP_FREE, patient.opRoom, patient.opEdTime, patient.id));
opRecord.put(patient.opRoom, opRecord.computeIfAbsent(patient.opRoom, it -> 0) + patient.opTime);
}
break;
case Event.EVENT_RC_FREE:
availableRcRoom.add(event.roomId);
break;
}
}
currentTimeMin -= mPreRcRoom;
p.p(" Patient Operating Room Recovery Room\n" +
" # Name Room# Begin End Bed# Begin End\n" +
" ------------------------------------------------------\n");
for (Patient patient : ps) {
p.pn(patient.toString(startHour));
}
p.pn();
p.p("Facility Utilization\n" +
"Type # Minutes % Used\n" +
"-------------------------\n");
for (int i = 0; i < opRoomCount; i++) {
p.pn(String.format("Room %2d%8d %5.2f", i + 1, opRecord.computeIfAbsent(i, it -> 0), opRecord.computeIfAbsent(i, it -> 0) * 100.0 / currentTimeMin));
}
for (int i = 0; i < rcRoomCount; i++) {
p.pn(String.format("Bed %2d%8d %5.2f", i + 1, rcRecord.computeIfAbsent(i, it -> 0), rcRecord.computeIfAbsent(i, it -> 0) * 100.0 / currentTimeMin));
}
p.pn();
}
}
}
class Event implements Comparable {
static final int EVENT_OP_FREE = 0, EVENT_OP_USE = 1, EVENT_RC_FREE = 2, EVENT_RC_USE = 3;
int type, happenTime, roomId, patientId = -1;
Event(int type, int roomId, int happenTime, int patientId) {
this.type = type;
this.roomId = roomId;
this.happenTime = happenTime;
this.patientId = patientId;
}
@Override
public int compareTo(Event o) {
int time = happenTime - o.happenTime;
if (time != 0) {
return time;
}
int typeDiff = o.type - type;
if (typeDiff != 0) {
return typeDiff;
}
return roomId - o.roomId;
}
}
class Patient {
String name;
int id, opTime, rcTime, opRoom, rcRoom, opStTime, rcStTime, opEdTime, rcEdTime;
public Patient(int id, String name, int opTime, int rcTime) {
this.id = id;
this.name = name;
this.opTime = opTime;
this.rcTime = rcTime;
}
public String toString(int startTimeHour) {
// 1 Jones 1 7:00 7:28 3 7:33 9:53
StringBuilder builder = new StringBuilder();
int opStH = startTimeHour + opStTime / 60;
int opStM = opStTime % 60;
int opEdH = startTimeHour + opEdTime / 60;
int opEdM = opEdTime % 60;
int rcStH = startTimeHour + rcStTime / 60;
int rcStM = rcStTime % 60;
int rcEdH = startTimeHour + rcEdTime / 60;
int rcEdM = rcEdTime % 60;
return String.format("%2d %-9s%3d %2d:%02d %2d:%02d %2d %2d:%02d %2d:%02d"
, id + 1, name, opRoom + 1, opStH, opStM, opEdH, opEdM, rcRoom + 1, rcStH, rcStM, rcEdH, rcEdM);
}
}