vector<int> v[N];
v[i]:编号为i的可用区所占有的所有计算节点
map<int,set<int>> mp;
mp[x]:编号为x的应用所在的所有可用区
map<int,set<int>> mpp;
mpp[x]:编号为x的应用所在的所有计算节点
int f,a,na,pa,paa,paar;
f:当前组的任务个数
a:当前任务所属的应用编号
na:当前任务必须要运行在编号为na的可用区,na=0时无要求
pa:当前任务必须要运行在编号为pa的应用所在的可用区,pa=0时无要求
paa:当前任务不可运行在编号为paa的应用所在的计算节点,paa=0时无要求
paar:paa的要求是必须满足还是尽量满足
处理思路:
筛选:对na和pa要求进行处理,na要求必须运行在na可用区,pa要求必须运行在pa应用所在的可用区,两者都是对可用区的限制,v[N]记录了每个可用区所占有的计算节点,利用v[N]记录同时满足na和pa要求的可用区占有的所有计算节点,接下来只需对计算节点处理。
排序:利用优先队列和结构体,将na和pa筛选出来的所有计算节点排序。
安排任务:1、每次取出最优的那个节点,判断是否满足paa要求,要求不能与paa的计算节点为同一个,而mpp[paa]记录了paa应用所在的所有计算节点,因此只需判断当前节点是否在mpp[paa]中,若在,意味着不满足paa要求,那么取出下一个最优的节点。 2、若对paa进行了要求,但当前任务没有安排完且可用的计算节点个数为0,那么考虑paar是否为0,若为0,则重新进行一次1步骤,此次不需再判断是否满足paa要求了。
原题链接:计算机软件能力认证考试系统
#include <iostream>
#include <vector>
#include <queue>
#include <map>
#include <set>
using namespace std;
const int N=1010;
int n,m,g,f,a,na,pa,paa,paar;
vector<int> v[N];//v[i]表示第i的可用区所占有的所有计算节点
map<int,set<int>> mp;//mp[x]表示第x个应用所在的所有可用区
map<int,set<int>> mpp;//mp[x]表示第x个应用所在的所有计算节点
struct Node{//计算节点
int id,fa,cnt;//编号,所在可用区的编号,任务个数
bool operator < (const Node &a) const{//优先队列排序
if(cnt!=a.cnt) return cnt>a.cnt;
return id>a.id;
}
}node[N];
int main()
{
cin>>n>>m;
for(int i=1;i<=n;i++){
cin>>node[i].fa;
node[i].cnt=0; node[i].id=i;
v[node[i].fa].push_back(i);//统计v[N]
}
cin>>g;
while(g--){
cin>>f>>a>>na>>pa>>paa>>paar;
priority_queue<Node> q;//优先队列,满足na和pa要求的所有计算节点
queue<int> qu;//所有可行的节点编号,存两次,因为paar=0时可能要重新排序
if(pa){//必须运行在pa应用所在的可用区
for(auto it=mp[pa].begin();it!=mp[pa].end();it++){
if(!na||*it==na){//na为0时记录pa所有的可用区,否则仅当pa的可用区包含na时记录
for(int j=0;j<v[*it].size();j++){
qu.push(v[*it][j]);
q.push(node[v[*it][j]]);
}
}
}
}
else if(na){//pa=0,且必须运行在na可用区
for(int j=0;j<v[na].size();j++){
qu.push(v[na][j]);
q.push(node[v[na][j]]);
}
}
else{//na=0且pa=0,对可用区无要求,那么所有计算节点都符合要求
for(int j=1;j<=n;j++){
qu.push(j);
q.push(node[j]);
}
}
int ass[2*N]={0},i;
for(i=1;i<=f&&!q.empty();i++){
int k=q.top().id; q.pop();
ass[i]=node[k].id;
while(paa&&mpp[paa].find(ass[i])!=mpp[paa].end()){//判断是否满足paa要求
if(q.empty()){//没有可行的节点了
ass[i]=0; break;
}
k=q.top().id; q.pop();//更新k个ass[i]
ass[i]=node[k].id;
}
if(!ass[i]) break;//没有可行的节点,退出
node[k].cnt++;//第k个节点的任务数+1
mp[a].insert(node[k].fa);//更新第a个应用所在的可用区
mpp[a].insert(node[k].id);//更新第a个应用所在的计算节点
q.push(node[k]);
}
if(paa&&!paar&&i<=f){//如果任务没有安排完且paa是尽量满足的
while(!qu.empty()){//重新排序
q.push(node[qu.front()]);
qu.pop();
}
for(;i<=f&&!q.empty();i++){//与之前一样,只是无需判断是否满足paa了
int k=q.top().id; q.pop();
ass[i]=node[k].id;
node[k].cnt++;
mp[a].insert(node[k].fa);
mpp[a].insert(node[k].id);
q.push(node[k]);
}
}
for(int i=1;i<=f;i++) cout<<ass[i]<<" ";
cout<<endl;
}
return 0;
}