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

解题思路:

严格按照题目的要求来做,读题后把关键信息记录在草稿纸上。题目要求根据三个方面进行筛选:节点亲和性,任务亲和性,任务反亲和性。

  • 计算节点亲和性

计算任务必须在指定可用区上运行。

  • 计算任务亲和性

计算任务必须和指定应用的计算任务在同一可用区上运行。

  • 计算任务反亲和性

计算任务不能和指定应用的计算任务在同一个计算节点上运行。

不难发现3个要求中的高频词汇:指定应用。我们可以将所有应用信息(运行节点,运行区域)以结构体的方式储存在动态数组vector里(结构体内部还要定义集合set)来完成筛选和安排时的信息检索与存入,但是根据输入规则,应用数量上限为10^9,数量级太大,相应的检索与存入耗时较大,因此必须转换思路。我最后采用的是定义结构体AREA,储存可用区内部的节点编号和应用编号;定义结构体CPU,储存节点的编号,所属可用区编号和任务数量,代码如下

struct AREA               
{
    set<int> clist;
    set<int> appl;
};

struct CPU                
{
    int cid;
    int aid;
    int tasks;
    set<int> appl;
};

查看输入格式和样例,用输入格式的名字为变量命名,按照题目的要求筛选节点

cin >> f >> a >> na >> pa >> paa >> paar;

vector<int> cpul;

if(na == 0)
{
	for(int i = 0; i < point_num; i++)
	{
		int aid = point_info[i].aid;
		if(pa != 0 && area[aid].appl.count(pa)==0)
			continue;
		if(paa != 0 && point_info[i].appl.count(paa)==1)
			continue;
		cpul.push_back(i);
	}
}
else
{
	for(auto it = area[na].clist.begin(); it != area[na].clist.end(); it++)
	{
		if(pa != 0 && area[na].appl.count(pa)==0)
			continue;
		if(paa != 0 && point_info[*it].appl.count(paa)==1)
			continue;
		cpul.push_back(*it);
	}
}

if(cpul.size() == 0)
{
	if(na == 0)
	{
		for(int i = 0; i < point_num; i++)
		{
			int aid = point_info[i].aid;
			if(pa != 0 && area[aid].appl.count(pa)==0)
				continue;
			if(paa != 0 && point_info[i].appl.count(paa)==1 && paar == 1)
				continue;
			cpul.push_back(i);
		}
	}
	else
	{
		for(auto it = area[na].clist.begin(); it != area[na].clist.end(); it++)
		{
			//int aid = point_info[*it].aid;          无效语句,增加工作量
			if(pa != 0 && area[na].appl.count(pa)==0)
				continue;
			if(paa != 0 && point_info[*it].appl.count(paa)==1 && paar == 1)
				continue;
			cpul.push_back(*it);
		}
	}
}

编写比较函数对可用节点列表进行排序

bool comp(int c1, int c2)                            
{
    if(cpu_info[c1].tasks == cpu_info[c2].tasks)
        return (c1 < c2);
    return (cpu_info[c1].tasks < cpu_info[c2].tasks);
}

 然后在排序前,需要特殊处理找不到节点的情况,因为空数组不需要排序,并且C++的STL容器和C语言的数组在用指针调用的时候都不会检查指针的合法性,如果数组为空,编译能通过但是运行到调用指针的那一行就会崩溃。

sort(cpul.begin(), cpul.end(), comp);  //会崩溃
if(cpul.size() == 0)                     //正确代码    
    printf("%d ", 0);
else       
    sort(cpul.begin(), cpul.end(), comp);

 满分代码

#include <iostream>
#include <vector>
#include <set>
#include <algorithm>

using namespace std;

struct AREA               
{
    set<int> clist;
    set<int> appl;
};

struct CPU                
{
    int cid;
    int aid;
    int tasks;
    set<int> appl;
};

int point_num, area_num;
CPU *cpu_info;                                       //设置指针类型,方便函数调用

bool comp(int c1, int c2)                            //比较参数
{
    if(cpu_info[c1].tasks == cpu_info[c2].tasks)
        return (c1 < c2);
    return (cpu_info[c1].tasks < cpu_info[c2].tasks);
}

int main()
{

    scanf("%d %d", &point_num, &area_num);

    AREA area[area_num+1];
    CPU point_info[point_num];
    cpu_info = point_info;

    for(int i = 0; i < point_num; i++)
    {
        int father_area;
        scanf("%d", &father_area);
        point_info[i].aid = father_area;
        point_info[i].cid = i;
        point_info[i].tasks = 0;          //这里的初始化很重要,不然后面在比较的时候会报错
        area[father_area].clist.insert(i);
    }



    int group_num;
    scanf("%d", &group_num);                  //压缩任务条数
    for(int num = 0; num < group_num; num++)
    {
        int times = 0;

        int f,a, na, pa, paa, paar;
        cin >> f >> a >> na >> pa >> paa >> paar;

        vector<int> cpul;
start:
        if(na == 0)
        {
            for(int i = 0; i < point_num; i++)
            {
                int aid = point_info[i].aid;
                if(pa != 0 && area[aid].appl.count(pa)==0)
                    continue;
                if(paa != 0 && point_info[i].appl.count(paa)==1)
                    continue;
                cpul.push_back(i);
            }
        }
        else
        {
            for(auto it = area[na].clist.begin(); it != area[na].clist.end(); it++)
            {
                if(pa != 0 && area[na].appl.count(pa)==0)
                    continue;
                if(paa != 0 && point_info[*it].appl.count(paa)==1)
                    continue;
                cpul.push_back(*it);
            }
        }



        if(cpul.size() == 0)
        {
            if(na == 0)
            {
                for(int i = 0; i < point_num; i++)
                {
                    int aid = point_info[i].aid;
                    if(pa != 0 && area[aid].appl.count(pa)==0)
                        continue;
                    if(paa != 0 && point_info[i].appl.count(paa)==1 && paar == 1)
                        continue;
                    cpul.push_back(i);
                }
            }
            else
            {
                for(auto it = area[na].clist.begin(); it != area[na].clist.end(); it++)
                {
                    if(pa != 0 && area[na].appl.count(pa)==0)
                        continue;
                    if(paa != 0 && point_info[*it].appl.count(paa)==1 && paar == 1)
                        continue;
                    cpul.push_back(*it);
                }
            }
        }



        if(times < f)
        {
            if(cpul.size() == 0)            //指针开始处不能为空,否则编译能过但是无法运行
                printf("%d ", 0);
            else
            {
                sort(cpul.begin(), cpul.end(), comp);
                printf("%d ",*cpul.begin()+1);
                point_info[*cpul.begin()].tasks += 1;
                point_info[*cpul.begin()].appl.insert(a);
                area[point_info[*cpul.begin()].aid].appl.insert(a);//此处需要重新筛选
            }
            times++;
            cpul.clear();
            goto start;
        }
        printf("\n");
    }

    return 0;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Andy_Xie007

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值