题目链接:https://vjudge.net/problem/UVA-212
题意摘自《算法禁赛入门经典》
题目大意
医院里有 N(N ≤ 10)个手术室和 M(M ≤ 30)个恢复室。每个病人首先会被分配到一个手术室,手术后会被分配到一个恢复室。从任意手术室到任意恢复室的时间均为 t1,准备一个 手术室和恢复室的时间分别为 t2 和 t3 (一开始所有手术室和恢复室均准备好,只有接待完一个病人之后才需要为下一个病人准备)。
K 名(K ≤ 100)病人按照花名册顺序排队,T 点钟准时开放手术室。每当有准备好的手术室时,队首病人进入其中编号最小的手术室。手术结束后,病人应立刻进入编号最小的恢复室。如果有多个病人同时结束手术,在编号较小的手术室做手术的病人优先进入编号较小的恢复室。输入保证病人无须排队等待恢复室。
输入 N、M、T、t1、t2、t3、K 和 K 名病人的名字、手术时间和恢复时间,模拟这个过程。
分析
要点:
- 多组数据,数据之间空一行,每组数据表间空一行。
- 0 个病人的情况。
- 手术结束时间相同的,手术室编号小的先安排。
- 手术完成后应当立即选择恢复室并移动。
代码如下
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 #define INIT() ios::sync_with_stdio(false);cin.tie(0);cout.tie(0); 5 #define Rep(i,n) for (int i = 0; i < (int)(n); ++i) 6 #define For(i,s,t) for (int i = (int)(s); i <= (int)(t); ++i) 7 #define rFor(i,t,s) for (int i = (int)(t); i >= (int)(s); --i) 8 #define ForLL(i, s, t) for (LL i = LL(s); i <= LL(t); ++i) 9 #define rForLL(i, t, s) for (LL i = LL(t); i >= LL(s); --i) 10 #define foreach(i,c) for (__typeof(c.begin()) i = c.begin(); i != c.end(); ++i) 11 #define rforeach(i,c) for (__typeof(c.rbegin()) i = c.rbegin(); i != c.rend(); ++i) 12 13 #define pr(x) cout << #x << " = " << x << " " 14 #define prln(x) cout << #x << " = " << x << endl 15 16 #define LOWBIT(x) ((x)&(-x)) 17 18 #define ALL(x) x.begin(),x.end() 19 #define INS(x) inserter(x,x.begin()) 20 #define UNIQUE(x) x.erase(unique(x.begin(), x.end()), x.end()) 21 #define REMOVE(x, c) x.erase(remove(x.begin(), x.end(), c), x.end()); // 删去 x 中所有 c 22 #define TOLOWER(x) transform(x.begin(), x.end(), x.begin(),::tolower); 23 #define TOUPPER(x) transform(x.begin(), x.end(), x.begin(),::toupper); 24 25 #define ms0(a) memset(a,0,sizeof(a)) 26 #define msI(a) memset(a,0x3f,sizeof(a)) 27 #define msM(a) memset(a,-1,sizeof(a)) 28 29 #define MP make_pair 30 #define PB push_back 31 #define ft first 32 #define sd second 33 34 template<typename T1, typename T2> 35 istream &operator>>(istream &in, pair<T1, T2> &p) { 36 in >> p.first >> p.second; 37 return in; 38 } 39 40 template<typename T> 41 istream &operator>>(istream &in, vector<T> &v) { 42 for (auto &x: v) 43 in >> x; 44 return in; 45 } 46 47 template<typename T> 48 ostream &operator<<(ostream &out, vector<T> &v) { 49 Rep(i, v.size()) out << v[i] << " "[i == v.size() - 1]; 50 return out; 51 } 52 53 template<typename T1, typename T2> 54 ostream &operator<<(ostream &out, const std::pair<T1, T2> &p) { 55 out << "[" << p.first << ", " << p.second << "]" << " "; 56 return out; 57 } 58 59 inline int gc(){ 60 static const int BUF = 1e7; 61 static char buf[BUF], *bg = buf + BUF, *ed = bg; 62 63 if(bg == ed) fread(bg = buf, 1, BUF, stdin); 64 return *bg++; 65 } 66 67 inline int ri(){ 68 int x = 0, f = 1, c = gc(); 69 for(; c<48||c>57; f = c=='-'?-1:f, c=gc()); 70 for(; c>47&&c<58; x = x*10 + c - 48, c=gc()); 71 return x*f; 72 } 73 74 template<class T> 75 inline string toString(T x) { 76 ostringstream sout; 77 sout << x; 78 return sout.str(); 79 } 80 81 inline int toInt(string s) { 82 int v; 83 istringstream sin(s); 84 sin >> v; 85 return v; 86 } 87 88 //min <= aim <= max 89 template<typename T> 90 inline bool BETWEEN(const T aim, const T min, const T max) { 91 return min <= aim && aim <= max; 92 } 93 94 typedef unsigned int uI; 95 typedef long long LL; 96 typedef unsigned long long uLL; 97 typedef vector< int > VI; 98 typedef vector< bool > VB; 99 typedef vector< char > VC; 100 typedef vector< double > VD; 101 typedef vector< string > VS; 102 typedef vector< LL > VL; 103 typedef vector< VI > VVI; 104 typedef vector< VB > VVB; 105 typedef vector< VS > VVS; 106 typedef vector< VL > VVL; 107 typedef vector< VVI > VVVI; 108 typedef vector< VVL > VVVL; 109 typedef pair< int, int > PII; 110 typedef pair< LL, LL > PLL; 111 typedef pair< int, string > PIS; 112 typedef pair< string, int > PSI; 113 typedef pair< string, string > PSS; 114 typedef pair< double, double > PDD; 115 typedef vector< PII > VPII; 116 typedef vector< PLL > VPLL; 117 typedef vector< VPII > VVPII; 118 typedef vector< VPLL > VVPLL; 119 typedef vector< VS > VVS; 120 typedef map< int, int > MII; 121 typedef unordered_map< int, int > uMII; 122 typedef map< LL, LL > MLL; 123 typedef map< string, int > MSI; 124 typedef map< int, string > MIS; 125 typedef multiset< int > mSI; 126 typedef set< int > SI; 127 typedef stack< int > SKI; 128 typedef deque< int > DQI; 129 typedef queue< int > QI; 130 typedef priority_queue< int > PQIMax; 131 typedef priority_queue< int, VI, greater< int > > PQIMin; 132 const double EPS = 1e-8; 133 const LL inf = 0x7fffffff; 134 const LL infLL = 0x7fffffffffffffffLL; 135 const LL mod = 1e9 + 7; 136 const int maxN = 1e4 + 7; 137 const LL ONE = 1; 138 const LL evenBits = 0xaaaaaaaaaaaaaaaa; 139 const LL oddBits = 0x5555555555555555; 140 141 struct Time { 142 int val = 0; // 总的分钟数 143 144 bool operator< (const Time &x) const { 145 return val < x.val; 146 } 147 148 bool operator== (const Time &x) const { 149 return val == x.val; 150 } 151 152 bool operator> (const Time &x) const { 153 return val > x.val; 154 } 155 156 Time operator+ (const int &k) const { 157 Time ret; 158 ret.val = val + k; 159 return ret; 160 } 161 162 Time operator+ (const Time &x) const { 163 Time ret; 164 ret.val = val + x.val; 165 return ret; 166 } 167 168 string getString() { 169 string ret; 170 ret = toString(val / 60) + ":"; 171 if((val % 60) / 10 == 0) ret += "0"; 172 ret += toString(val % 60); 173 return ret; 174 } 175 }; 176 177 struct Patient { 178 int id; // 病人在,名册上的 id 179 string name; // 病人名字 180 int surgeryTime; // 病人手术时间 181 int recoveryTime; // 病人恢复时间 182 183 int surgeryRoomId; // 所进行手术的手术室 id 184 Time surgeryBeginTime; // 手术开始时间 185 Time surgeryEndTime; // 手术结束时间 186 187 int recoveryRoomId; // 所进行恢复的恢复室 id 188 Time recoveryBeginTime; // 恢复开始时间 189 Time recoveryEndTime; // 恢复结束时间 190 191 Patient(int x) : id(x) {} 192 }; 193 194 istream& operator >> (istream& in, Patient& x){ 195 in >> x.name >> x.surgeryTime >> x.recoveryTime; 196 return in; 197 } 198 199 ostream& operator << (ostream& out, Patient& x){ 200 printf("%2d %-8s %2d %5s %5s %2d %5s %5s", x.id, x.name.c_str(), x.surgeryRoomId, x.surgeryBeginTime.getString().c_str(), x.surgeryEndTime.getString().c_str(), x.recoveryRoomId, x.recoveryBeginTime.getString().c_str(), x.recoveryEndTime.getString().c_str()); 201 return out; 202 } 203 204 struct Facility { 205 int id; // 设施 id 206 string type; // 设施类型 207 int timeUsed; // 设施被使用的时间 208 double usedPercent; // 使用时间百分比 209 210 Facility(int x, string y) { 211 id = x; 212 type = y; 213 timeUsed = 0; 214 usedPercent = 0; 215 } 216 }; 217 218 ostream& operator << (ostream& out, const Facility& x) { 219 printf("%-4s %2d %7d %6.2f", x.type.c_str(), x.id, x.timeUsed, x.usedPercent); 220 return out; 221 } 222 223 struct Event { 224 // 1 代表患者可进行手术事件 225 // 2 代表患者可进行恢复事件 226 // 3 代表手术室空闲事件 227 // 4 代表恢复室空闲事件 228 int type; 229 int idx; // 对应数组下表 230 Time time; // 事件可进行时间 231 232 Event(int x, int y, Time z) { 233 type = x; 234 idx = y; 235 time = z; 236 } 237 238 bool operator< (const Event &x) const { 239 return time > x.time || time == x.time && idx > x.idx; 240 } 241 }; 242 243 int N; // 手术室数量,小于等于 10 244 vector< Facility > rooms; // 手术室房间数组 245 int M; // 恢复室数量,小于等于 30 246 vector< Facility > beds; // 恢复室床数组 247 Time startTime; // 一天中医院的开始营业时间,整点,24小时格式 248 Time endTime; // 所有手术的结束时间 249 int totalTime; // 手术总持续时间 250 int tranTime; // 手术室转移恢复室时间(分钟) 251 int surgeryResetTime; // 手术室准备时间(分钟) 252 int recoveryResetTime; // 恢复室准备时间(分钟) 253 vector< Patient > roster; // 病人名册 254 int patientNum; // 病人人数 255 int tmp; 256 257 struct RoomCmp { 258 bool operator() (int x, int y) { 259 return rooms[x].id > rooms[y].id; 260 } 261 }; 262 263 struct BedCmp { 264 bool operator() (int x, int y) { 265 return beds[x].id > beds[y].id; 266 } 267 }; 268 269 struct RecoveryComp { 270 bool operator() (int x, int y) { 271 if(roster[x].surgeryEndTime == roster[y].surgeryEndTime) return roster[x].surgeryRoomId > roster[y].surgeryRoomId; 272 return roster[x].surgeryEndTime > roster[y].surgeryEndTime; 273 } 274 }; 275 276 priority_queue< Event > Q; // 活动队列 277 QI surgeryQ; // 等待手术队列 278 priority_queue< int, VI, RecoveryComp > recoveryQ; // 等待恢复队列 279 priority_queue< int, VI, RoomCmp > roomQ; // 手术室空闲队列 280 priority_queue< int, VI, BedCmp > bedQ; // 恢复室空闲队列 281 282 void init() { 283 rooms.clear(); 284 beds.clear(); 285 endTime = startTime; 286 roster.clear(); 287 288 while(!Q.empty()) Q.pop(); 289 while(!surgeryQ.empty()) surgeryQ.pop(); 290 while(!recoveryQ.empty()) recoveryQ.pop(); 291 while(!roomQ.empty()) roomQ.pop(); 292 while(!bedQ.empty()) bedQ.pop(); 293 } 294 295 bool readData() { 296 if(!(cin >> N >> M >> tmp >> tranTime >> surgeryResetTime >> recoveryResetTime >> patientNum)) return false; 297 startTime.val = tmp * 60; 298 299 init(); 300 301 Rep(i, N) rooms.PB(Facility(i + 1, "Room")); 302 Rep(i, M) beds.PB(Facility(i + 1, "Bed")); 303 304 Rep(i, patientNum) { 305 roster.PB(Patient(i + 1)); 306 cin >> roster[i]; 307 } 308 309 return true; 310 } 311 312 void printSheet() { 313 printf(" Patient Operating Room Recovery Room "); 314 printf(" # Name Room# Begin End Bed# Begin End "); 315 printf(" ------------------------------------------------------ "); 316 Rep(i, patientNum) cout << roster[i] << endl; 317 318 cout << endl; 319 320 printf("Facility Utilization "); 321 printf("Type # Minutes % Used "); 322 printf("------------------------- "); 323 Rep(i, N) { 324 if(totalTime) rooms[i].usedPercent = 100.0 * rooms[i].timeUsed / totalTime; 325 cout << rooms[i] << endl; 326 } 327 Rep(i, M) { 328 if(totalTime) beds[i].usedPercent = 100.0 * beds[i].timeUsed / totalTime; 329 cout << beds[i] << endl; 330 } 331 } 332 333 void solve() { 334 Time nowTime; 335 Rep(i, patientNum) Q.push(Event(1, i, startTime)); 336 Rep(i, N) Q.push(Event(3, i, startTime)); 337 Rep(i, M) Q.push(Event(4, i, startTime)); 338 339 while(!Q.empty()) { 340 nowTime = Q.top().time; 341 342 while(!Q.empty() && nowTime == Q.top().time) { // 把这个时间到到达的活动全取出来 343 Event e = Q.top(); Q.pop(); 344 345 switch(e.type) { 346 case 1:{ 347 surgeryQ.push(e.idx); 348 break; 349 } 350 case 2:{ 351 recoveryQ.push(e.idx); 352 break; 353 } 354 case 3:{ 355 roomQ.push(e.idx); 356 break; 357 } 358 case 4:{ 359 bedQ.push(e.idx); 360 break; 361 } 362 default:{ 363 assert(false); 364 } 365 } 366 } 367 368 // 如果有人等待做手术并且有手术室可用,就分配手术室 369 while(!surgeryQ.empty() && !roomQ.empty()) { 370 int pid = surgeryQ.front(); surgeryQ.pop(); 371 int rid = roomQ.top(); roomQ.pop(); 372 Patient &p = roster[pid]; 373 Facility &f = rooms[rid]; 374 375 p.surgeryRoomId = f.id; 376 p.surgeryBeginTime = nowTime; 377 p.surgeryEndTime = p.surgeryBeginTime + p.surgeryTime; 378 379 f.timeUsed += p.surgeryTime; 380 381 Q.push(Event(2, pid, p.surgeryEndTime)); 382 Q.push(Event(3, rid, p.surgeryEndTime + surgeryResetTime)); 383 } 384 385 // 如果有人等待恢复并且有恢复室可用,就分配恢复室 386 while(!recoveryQ.empty() && !bedQ.empty()) { 387 int pid = recoveryQ.top(); recoveryQ.pop(); 388 int bid = bedQ.top(); bedQ.pop(); 389 Patient &p = roster[pid]; 390 Facility &f = beds[bid]; 391 392 p.recoveryRoomId = f.id; 393 p.recoveryBeginTime = nowTime + tranTime; 394 p.recoveryEndTime = p.recoveryBeginTime + p.recoveryTime; 395 396 f.timeUsed += p.recoveryTime; 397 398 endTime = max(endTime, p.recoveryEndTime); 399 400 Q.push(Event(4, bid, p.recoveryEndTime + recoveryResetTime)); 401 } 402 } 403 } 404 405 int main() { 406 //freopen("MyOutput.txt","w",stdout); 407 //freopen("input.txt","r",stdin); 408 //INIT(); 409 while(readData()) { 410 solve(); 411 totalTime = endTime.val - startTime.val; 412 printSheet(); 413 cout << endl; 414 } 415 return 0; 416 }