題目鏈接:問題 A: 任務調度
#include<cstdio>
#include<iostream>
#include<cmath>
#include<string>
#include<algorithm>
#include<map>
#include<queue>
using namespace std;
//任務結構體定義
struct task{
//任務名字
string name;
//任務優(yōu)先數
int priority;
//比較符號小于的重載,以便用于優(yōu)先隊列使用
friend bool operator < (task a, task b){
//首先按照優(yōu)先數越小的排在前面,其次按照名字的字典序排序
if(a.priority != b.priority)
return a.priority > b.priority;
else
return a.name > b.name;
}
};
//處理一個任務調度序列
//參數s為當前輸入的一個調度序列,pq為優(yōu)先隊列,have為map序列,其中存儲了已經處理過的任務
void load(string s, priority_queue<task> &pq, map<string, int> &have){
string word = "";
task t;
//從0位置找到左括號,這個任務為當前輸入的前序任務,后面括號中為后續(xù)任務
for(int i = 0; s[i] != '('; i++)
word += s[i];
//如果這個前序任務在have不存在,說明第一次出現,將其優(yōu)先數定義為1
//優(yōu)先數越低表示優(yōu)先級越高,這樣定義是因為可由優(yōu)先數從低到高累加,
//如果定義為優(yōu)先數越大優(yōu)先級越高,首先問題就是不知道到底有多少個任務,因此不知定義最大優(yōu)先數為多少合適
if(have[word] == 0){
//第一次出現則記錄該任務并初始化其優(yōu)先數為最低即優(yōu)先級最大
t.name = word;
t.priority = 1;
//在map序列中做記錄,該任務已經存在
have[word] = t.priority;
//加入優(yōu)先隊列
pq.push(t);
}
//刪除左括號及以前的字符串
s.erase(s.begin(), s.begin()+s.find("(")+1);
//處理后續(xù)任務,他們都是需要前序任務完成才能執(zhí)行,因此他們的優(yōu)先級也只比前序任務少一個級別
//因此將前序任務word的優(yōu)先數加1(優(yōu)先級則降低,temp存儲)作為后續(xù)的任務的優(yōu)先數
int temp = have[word] + 1;
//重復使用word
word = "";
for(int i = 0; i < s.size(); i++){
//如果出現逗號或者右括號,表面又統(tǒng)計了一個任務,如果這個任務不是NULL并且是第一次出現就進行處理
if((s[i] == ',' || s[i] == ')') && (word != "NULL" && have[word] == 0)){
//處理方式和前面相同
t.name = word;
t.priority = temp;
have[word] = t.priority;
pq.push(t);
word = "";
}
//沒出現逗號之類則累加到當前單詞上
else
word += s[i];
}
}
int main(){
int n;
while(scanf("%d", &n) != EOF){
//定義一個優(yōu)先隊列,存儲調度的任務
priority_queue<task> pq;
//map序列,存放已經存在的任務(鍵)及其對應的優(yōu)先級(值)
//map的定義主要用于判斷一個任務是否是第一次出現,由于map不存在某個鍵的值時,該鍵的默認值時0
//因此可通過判斷其對應的值是否為0來判斷一個任務是否第一次出現
map<string, int> have;
string s;
for(int i = 0; i < n; i++){
cin >> s;
load(s, pq, have);
}
//任務序列輸出
while(!pq.empty()){
cout << pq.top().name;
if(pq.size() > 1)
cout << " ";
else
cout << endl;
pq.pop();
}
}
return 0;
}