第25次CCF CSP(202203) T3题解 计算资源调度器(C++)

原题链接:

第25次CCF CSP T3

解题思路:

用的stl挺多的,把需要用到的信息写成变量,再看题目要求来就ok了

1.一种方法是对每组任务的每个子任务都筛选再排序一遍

2.另一种是只筛选一次(paar=0可能要两次),把所有可用节点放堆中,每个子任务取堆顶节点

2相对于1要快很多但是两种方法思路大致相同也都能过

这里展示2方法的代码,详细思路都在注释里了

代码:

#include<iostream>
#include<cstdio>
#include<map>
#include<string>
#include<queue>
#include<vector>
using namespace std;

struct Node{   //存放计算节点的结构体
    int id;    //节点编号
    int cnt;   //节点运行的任务数
    int from;  //节点所在可用区的编号
    map<int,bool> book; //节点运行了什么任务
    bool operator < (const Node &a)const{ //重载运算符,先比较cnt再比较id
        if(cnt!=a.cnt) return cnt>a.cnt;
        else return id>a.id;
    }
}node[1006];

map<int,bool> qu[1006]; //每个可用区运行了什么任务
int n,m,g;

//过滤可用的节点入堆,最后返回该堆
//每次过滤都遍历一遍所有节点
priority_queue<Node> chose(int &a,int &na,int &pa,int paa,int &paar){
    //过滤节点亲和性
    vector<Node> c1;
    if(na){
        for(int j=1;j<=n;j++){
            if(node[j].from==na) c1.push_back(node[j]);
        }
    }
    else{
        for(int j=1;j<=n;j++) c1.push_back(node[j]);
    }
    //过滤任务亲和性
    vector<Node> c2;
    if(pa){
        for(int j=0;j<c1.size();j++){
            if(qu[c1[j].from][pa]) c2.push_back(c1[j]);
        }
    }
    else c2=c1;
    //过滤任务反亲和性
    vector<Node> c3;
    if(paa){
        for(int j=0;j<c2.size();j++){
            if(!c2[j].book[paa]) c3.push_back(c2[j]);
        }
    }
    else c3=c2;
    //把所有可用节点入堆排序
    priority_queue<Node> final;
    for(int j=0;j<c3.size();j++) final.push(c3[j]);
    //final中存着所有排好序的可用节点
    return final;
}

//打印答案并更新节点信息
int ans(int tf,priority_queue<Node> &final,int &a,int paa){
    while(tf&&!final.empty()){//任务都分配完了或者可用节点没了都要结束循环
        Node temp=final.top();
        final.pop();
        cout<<temp.id<<' ';
        //更新节点信息
        node[temp.id].cnt++;
        node[temp.id].book[a]=true;
        qu[temp.from][a]=true;
        //如果反亲和性是它自己,则这个节点不可用了。否则还要把这个节点入堆
        if(a!=paa) temp.cnt++,final.push(temp);
        tf--;
    }
    return tf;
}

int main(){
    cin>>n>>m;
    for(int i=1;i<=n;i++) node[i].id=i; //初始化节点id
    for(int i=1;i<=n;i++){
        int temp;
        cin>>temp;
        node[i].from=temp;
    }
    cin>>g;
    while(g--){
        int f,a,na,pa,paa,paar;
        cin>>f>>a>>na>>pa>>paa>>paar;
        priority_queue<Node> final=chose(a,na,pa,paa,paar);
        int tf=ans(f,final,a,paa);
        if(tf&&!paar){//如果任务没分配完并且反亲和性不是必须的,那么再过滤一次,再打印一次
            final=chose(a,na,pa,0,paar);
            tf=ans(tf,final,a,0);
        }
        while(tf--) cout<<0<<' ';//剩下的是实在无法分配的任务,全输出0
        cout<<endl;
    }
    system("pause");
    return 0;
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值