UVA - 212 Use of Hospital Facilities

/*
  借鉴了:
  http://blog.csdn.net/xienaoban/article/details/52895020
  
  收获 & 总结:
  1. cout的输出格式控制
  http://blog.csdn.net/xienaoban/article/details/52895020
  
  2.vector可在定义时,指定大小并同一初始化
  http://blog.chinaunix.net/uid-26000296-id-3785610.html
  
*/


#include <iostream>
#include <string>
#include <vector>
#include <queue>
#include <iomanip>
#include <algorithm>
#define rep(i, n) for (int i = 1; i <= (n); i++)
#define output_time(t)  setw(2) << (t / 60) << ':' << setfill('0') << setw(2) << (t % 60) << setfill(' ') 
using namespace std;

struct room
{
	int id, at;
	room(){}
	room(int a, int b):id(a), at(b){}
	bool operator < (const room& r) const
	{
		if (at != r.at) return at > r.at;
		return id > r.id;
	} //at为手术结束时间,id为手术室编号,优先队列优先级更大的先出队,故以这样的方式重载 
};

struct patient
{
	string name;
	int id, room, bed, top, tre, t1, t2, t3, t4;
};

bool mycmp(const patient &a, const patient &b)
{
	if (a.t2 != b.t2) return a.t2 < b.t2;
	return a.room < b.room;
}//at为手术结束时间,id为手术室编号,优先队列优先级更大的先出队,故以这样的方式重载 

int n, m, T, t1, t2, t3, k, Time;

int main()
{
	cin.tie(0);
	cin.sync_with_stdio(false);
	while (cin >> n)
	{
		cin >> m >> T >> t1 >> t2 >> t3 >> k;
		Time = 0, T *= 60;
		vector<int> Top(n + 1, 0), Tre(m + 1, 0); // 手术室、恢复室的利用时间
		vector<patient> patients(k + 1);
		vector<int> Bre(m + 1, T); //保存恢复室恢复的时间 
		priority_queue<room> Rop; // room for operation
		
		rep(i, n) Rop.push(room(i, T));
		
		rep(i, k)
		{
			auto &now(patients[i]);
			now.id = i;
			room tp(Rop.top()); //按优先级出队,此时出队的是该病人该进入的手术室
			Rop.pop();
			cin >> now.name >> now.top >> now.tre; //在手术室、恢复室所待的时间 
			now.t1 = tp.at;
			now.t2 = now.t1 + now.top; //手术结束时间 
			now.t3 = now.t2 + t1; //t1:从手术室到恢复室 
			now.t4 = now.t3 + now.tre;
			now.room = tp.id; //病人所在的手术室序号
			tp.at = now.t2 + t2; //手术室再次可用的时间,为病人离开时间,加上手术室恢复时间
			Top[tp.id] += now.top; //该手术室使用时间(最后要算时间利用率!)
			Rop.push(tp); 
		}
	
	
	sort(patients.begin() + 1, patients.end(), mycmp);
	
	rep(i, k)
	{
		auto &now(patients[i]);
		int j;
		for (j = 1; j <= m; j++)
		if (Bre[j] <= now.t2) break;
		now.bed = j;
		Bre[j] = now.t4 + t3;
		Tre[j] += now.tre; //该恢复室使用时间(最后要算时间利用率!) 
		Time = max(Time, now.t4);
	}
	sort(patients.begin() + 1, patients.end(), [] (patient &a, patient &b) {return a.id < b.id;});
	
	cout << " Patient          Operating Room          Recovery Room\n"
         << " #  Name     Room#  Begin   End      Bed#  Begin    End\n"
         << " ------------------------------------------------------\n";
         
    rep(i, k)
    {
    	auto &now (patients[i]);
    	cout << setw(2) << i << "  " << left << setw(10) << now.name << right << setw(2) << now.room << "   " 
			 << output_time(now.t1) << "   " << output_time(now.t2) << "     " << setw(2) << now.bed << "   "
			 << output_time(now.t3) << "   " << output_time(now.t4) << endl;
	}
	
	cout << endl
		 << "Facility Utilization" << endl << "Type  # Minutes  % Used" << endl
		 << "-------------------------" << endl;
	
	rep(i, n)
	{
		cout << "Room " << setw(2) << i << setw(8) << Top[i] << setw(8) << fixed << setprecision(2) 
			 << (Top[i] * 100.0 / (float)(Time - T) ) << endl;
	}
	
	rep(i, m)
	{
		cout << "Bed  " << setw(2) << i << setw(8) << Tre[i] << setw(8)
			 << fixed << setprecision(2) << (Tre[i] * 100.0 / (float)(Time - T) ) << endl;
	}
	cout << endl;
	
	}
	return 0;
}

/* 
  看过的法二:
  
  收获 && 总结:
  1. http://blog.csdn.net/wusecaiyun/article/details/48879899
  queue没有clear方法,但因为该题多组数据,要么在非空时,不断调用pop();要么在while循环内定义queue,则定义后默认为空,每次进入循环重新定义(法一采用)
  
  2. 这个博主对结构体的设计,感觉比法一更有条理,含义也更加清楚
  
  ROOM_BED 保存床位的使用时间(手术室床位 / 恢复室床位)和利用率(使用时间除以整个过程的总时间)
  
  PATIENT 保存病人信息,包括姓名、病人本身序号、手术室和恢复室的序号
  在手术室、恢复室的起止时间(除了第一组以外,停止时间是加上了手术 / 恢复室的准备时间的),手术、恢复的持续时间
  
  ROOM 保存手术/恢复室被使用的起止时间
  
  其实法一基本也存的是这些数据,但是没有法二中的直观,可见变量取名是挺重要的一件事
*/


posted @ 2017-09-18 08:19  mofushaohua  阅读(362)  评论(0编辑  收藏  举报