ccf csp第25次认证第三题 计算资源调度器

题目描述

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;
}
  • 8
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值