講解
- 設置一個將題幹hh:mm:ss時間轉化爲秒爲單位的時間的函數
- 利用一個優先隊列(這裏是一個小根堆,每次top爲時間最小的元素)保存每個窗口的當前時間
- 將每個人的個人信息用struct保存,包括到達時間和處理時間
- 將每個人以到達時間排序(由小到大),先到的先處理
- 開始模擬銀行工作:
1)
取出當前時間time_win(就是該窗口上一次處理的結束時間,初始化爲8*3600)最小的銀行窗口,接受最早到達的人的申請
2)
修改當前窗口的結束時間爲time_win + 處理人的執行時間process(這就是該窗口下一次可以接受申請的時間)
3)
將該窗口信息重新入隊,然後循環這三步,代碼中有詳細註釋
算法思路
思路源自於模擬正常銀行工作流程,哪個窗口先空閒哪個窗口工作,符合優先隊列的性質,然後先到的人先安排,所以要排序
代碼部分
代碼中包含了測試輸出語句,方便讀者copy後去測試pat例子,這裏已經註釋掉了,可以直接在pat提交
#include <iostream>
#include <cstdlib>
#include <algorithm>
#include <ostream>
#include <queue>
using namespace std;
/** 保存8:00 和 17:00 的秒進制時間 **/
const int Start = 8*3600;
const int End = 17*3600;
/** 建立一個結構體,保存每個人的到達時間和執行時間 **/
struct node{
int arr_time;
int pro_time;
bool operator < (const node& n1)const{
return this->arr_time < n1.arr_time;
}
// friend ostream& operator << (ostream& os,const node& n){
// os<<n.arr_time<<" "<<n.pro_time<<endl;
// return os;
// }
};
vector<node> people;
/** 時間轉化函數 **/
int time_int(string& s){
string hh = s.substr(0,2),mm = s.substr(3,2),ss = s.substr(6,2);
int hi = atoi(hh.c_str()),mi= atoi(mm.c_str()),si = atoi(ss.c_str());
return hi*3600 + mi*60 + si; //轉換成秒保存
}
int main()
{
int N,K;
cin>>N>>K;
/** 創建一個容量爲K的小根堆,表示k個窗口 **/
priority_queue<int,vector<int>,greater<int>> pq;
for(int i=0;i<K;i++) pq.push(Start);
for(int i=0;i<N;i++){
string arrive; // 到達時間
int process; // 辦理時間
cin>>arrive>>process;
people.push_back({time_int(arrive),process*60});
}
sort(people.begin(),people.end());
// cout<<"start = "<<Start<<endl;
// cout<<"End = "<<End<<endl;
// for(int i=0;i<people.size();i++){
// cout<<people[i];
// }
/** 處理每一個人 **/
double ans = 0;
int realN = 0;
for(int i=0;i<N;i++){
node f = people[i]; // 獲取最先到達的一個人
if(f.arr_time > End) continue; // 超時到達不處理
realN++;
// cout<<"i = "<<i<<endl;
int temp_win = pq.top(); // 獲取第一個空閒的窗口
// cout<<"第一個空閒窗口時間爲:"<<temp_win<<endl;
pq.pop();
int arr_time = f.arr_time;
if(arr_time <= temp_win){ // 到達時沒有空閒窗口,需要等待
ans += temp_win-arr_time; // 累計等待時間
temp_win += f.pro_time; // 修改當前窗口的下一次空閒時刻
pq.push(temp_win);
}else{ // 到達時有空閒窗口,無需等待直接工作
temp_win = arr_time + f.pro_time;
pq.push(temp_win);
}
}
printf("%.1f",ans/realN/60);
return 0;
}
pat運行結果
複雜度分析
- 時間複雜度:對N個人時間排序的時間爲O(NlogN),然後需要對每個人處理一次,還有入隊出隊的處理,處理時間爲O(N),隊列調整時間爲O(log(K)),整體時間複雜度爲O(max(Nlog(N),log(K)));
- 空間複雜度:優先隊列複雜度爲O(K),結構體信息複雜度爲O(N),整體複雜度爲O(K+N);
感謝大家觀看!歡迎評論區批評指正。