【CCF-CSP】202203-3计算资源调度器

 

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;
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值