题目描述
ccf csp第25次认证第三题 计算资源调度器
原题链接:
http://118.190.20.162/home.page
样例输入
10 4
1 1 1 1 1 2 2 2 2 2
6
2 1 4 1 2 1
6 1 1 0 1 1
1 2 2 0 0 0
6 1 2 0 2 1
5 2 2 0 1 0
11 3 0 1 3 0
样例输出
0 0
1 2 3 4 5 0
6
7 8 9 10 7 8
6 6 6 6 6
1 2 3 4 5 9 10 7 8 6 1
思路
题目有三个条件,建立三个状态数组,分别对应一种条件,只有三种条件同时满足才可以进行资源分配。
这道题比较坑的一点就是读入数据时pa、paa可能在前面没有出现过,如果没有出现过相当于pa、paa=0
C++ 代码
#include <iostream>
#include <cstring>
#include <algorithm>
#include <vector>
#include <set>
#include <unordered_map>
using namespace std;
const int N = 1010, M = 6010;//为什么要开6000,因为a、pa、paa的值可能不一样,最多2000组,所以
//要开2000*3=6000 (考试的时候出题人并没有在这里卡我们,所以开2010也能过)
int idx,ne[N],e[N],h[N],direct;
int n,m;
bool stna[N];
bool stpa[N];
bool stpaa[N];
unordered_map<int,int> mymap;//哈希表用于将1~1e9的应用号转换为数组能容纳(这里是1~6000)的应用号,因为直接开 //数组的话开不了1000000000这么大的数组
vector<set<int>> affair(M);//表示应用在哪些计算节点
int fa[N];//表示计算节点在哪个任务区
int node[N];//表示节点的任务数量
void add(int a,int b){
ne[idx]=h[a];
e[idx]=b;
h[a]=idx++;
}
//判断当前有无满足要求的计算节点,有则返回对应下标,没有则返回0
//三个if语句对应计算节点亲和性、计算任务亲和性、计算任务反亲和性这三个条件
int work(int a,int na,int pa,int paa,int paar){
if(!na){
memset(stna,true,sizeof stna);
}
else {
memset(stna,false,sizeof stna);
for(int i=h[na];i!=-1;i=ne[i]){
int j=e[i];
stna[j]=true;
}
}
if(!pa){
memset(stpa,true,sizeof stpa);
}
else{
memset(stpa,false,sizeof stpa);
set<int> must;
for(set<int>::iterator it=affair[pa].begin();it!=affair[pa].end();it++){
must.insert(fa[*it]);
}
for(auto key:must){
for(int i=h[key];i!=-1;i=ne[i]){
int j=e[i];
stpa[j]=true;
}
}
}
if(!paa){
memset(stpaa,true,sizeof stpaa);
}
else{
memset(stpaa,true,sizeof stpaa);
for(set<int>::iterator it=affair[paa].begin();it!=affair[paa].end();it++){
stpaa[*it]=false;
}
}
int besti=0;
for(int i=1;i<=n;i++){
if(stna[i]&&stpa[i]&&stpaa[i]){
if(besti==0) besti=i;
else if(node[i]<node[besti]) besti=i;
else if(node[i]==node[besti]&&i<besti) besti=i;
}
}
return besti;
}
int main(){
cin>>n>>m;
memset(h,-1,sizeof h);
for(int i=1;i<=n;i++) {
int x;
cin>>x;
fa[i]=x;
add(x,i);
}
int T;
cin>>T;
mymap.insert({0,0});
while(T--){
int f,a,na,pa,paa,paar;
scanf("%d%d%d%d%d%d",&f,&a,&na,&pa,&paa,&paar);
if(mymap.find(a)==mymap.end()){
mymap.insert({a,++direct});
}
if(mymap.find(pa)==mymap.end()){
mymap.insert({pa,++direct});
}
if(mymap.find(paa)==mymap.end()){
mymap.insert({paa,++direct});
}
int va=mymap[a];//利用哈希表将应用序号映射到一个比较小的区间
int vpa=mymap[pa];
int vpaa=mymap[paa];
while(f--){
int besti=work(va,na,vpa,vpaa,paar);
if(besti){
cout<<besti<<" ";
affair[va].insert(besti);
node[besti]++;
}
else if(paar==1){
cout<<0<<" ";
}
else{ //如果是尽量满足但是第一次没有满足条件的计算节点,那么忽略反亲和性这个条件再来一次
vpaa=0;
besti=work(va,na,vpa,vpaa,paar);
if(!besti) cout<<0<<" ";
else{
cout<<besti<<" ";
affair[va].insert(besti);
node[besti]++;
}
}
}
puts("");
}
return 0;
}