CSP202203-3

只用会用的STL,数组优先,结构体优先。

#include <bits/stdc++.h>
using namespace std;

/*
西西艾弗云有多个结点,每个结点都有唯一的编号。

西西艾弗云每个计算任务都有一个应用与之对应,每个应用可能
包含多个计算任务(一对多运算)

每个计算任务由一个特定的计算节点执行。

对于一个计算任务,主席那个它的计算节点一旦选定便不再更改,
在选定计算节点后,该计算节点的要求不再被考虑。

输入:
计算任务 和 要求
输出:
计算任务需要安排在哪个节点上

三种要求:
1. 计算任务在指定节点上运行
2. 计算任务必须和指定应用的计算任务在同一**可用区**上运行。
3. 计算任务不能和指定任务的计算任务在同一**计算节点**上运行。
(必须满足 or 尽量满足)

选择计算节点:
1. 过滤阶段,根据要求过滤出所有满足要求的计算节点。
如果没有满足要求的节点,且要求中有3,且为尽量满足,则
去除要求3,再过滤一边。如果还没有节点满足,则无法分配。
2. 将过滤后的计算节点排序:
	2.1选择此时计算任务数量最少的计算节点
	2.2选择编号最小的计算节点。

数据结构:
结构体:
计算节点
任务

*/

const int N = 1e3 + 10;

int n, m;
// 某个计算节点在哪个可用区中
int l[N];
// 某个区中有那些编号的计算节点
vector<int> st[N];
int sz[N];
//// 某个计算节点已经运行的任务应用类型
//vector<int> load[N];
int g;
struct Mission {
	int f;	//任务个数
	int a;	//应用编号
	// 任务的三种要求
	int rule1;
	int rule2;
	int rule3;
	// 第三种要求的种类
	int rule3_opt;
} mis[2 * N];

struct Node {
	int cnt; // 节点编号
	int l;	// 节点对应的可用区
	int sz; // 节点上分配的任务数

} node[N];

//确定某个应用在哪些任务区上运行。

vector<int> app_on_area[2 * N];
vector<int> app_on_node[2 * N];

// que 临时记录某个节点是否符合题意
int que[N];

// 对应用编号进行离散化,离散化到2e3范围内
int cnt;
unordered_map<int, int>  mp;

int func(int x) {
	if (mp.find(x) == mp.end()) {
		mp.insert({x, cnt++});
		return mp[x];
	} else {
		return mp[x];
	}
}

bool cmp(Node a, Node b) {
	if (a.sz == b.sz) {
		return a.cnt < b.cnt;
	} else
		return a.sz < b.sz;
}

int main() {
	scanf("%d %d", &n, &m);

	for (int i = 1; i <= n; i++) {
		int tmp;
		scanf("%d", &tmp);
		node[i].cnt = i;
		node[i].l = tmp;
		st[tmp].push_back(i);
	}

	scanf("%d", &g);

	for (int ct = 1; ct <= g; ct++) {
		scanf("%d %d %d %d %d %d", &mis[ct].f, &mis[ct].a,
		      &mis[ct].rule1, &mis[ct].rule2, &mis[ct].rule3,
		      &mis[ct].rule3_opt);

		// 对于同一批次的任务,也可能分类不同,所以
		// 先考虑对每个任务分别处理。
		for (int cc = 1; cc <= mis[ct].f; cc++) {
			memset(que, 0, sizeof que);

			// rule1处理
			if (mis[ct].rule1 != 0) {
				for (int j = 1; j <= n; j++) {
					if (node[j].l != mis[ct].rule1) {
						que[j]++;
					}
				}
			}
			// 符合条件的为0,不符合条件的为1.

			//离散化处理
			// rule2处理
			if (mis[ct].rule2 != 0) {
				// 运行 rule2 应用的节点
				if (mp.find(mis[ct].rule2) != mp.end()) {
					int tmp = func(mis[ct].rule2);
					for (int j = 0; j < app_on_area[tmp].size(); j++) {
						// 对应空闲区中的运算节点
						for (int k = 0; k < st[app_on_area[tmp][j]].size(); k++) {
							// 在 rule1可行的条件下,如果rule2也可行,则设置为2.
							if (que[st[app_on_area[tmp][j]][k]] == 0) {
								que[st[app_on_area[tmp][j]][k]] = 2;
							}
						}
					}
				}
			} else {
				for (int j = 1; j <= n; j++) {
					if (que[j] == 0) {
						que[j] = 2;
					}
				}
			}

			vector<Node> vv;
			vv.clear();
			int ans = 0;
			for (int j = 1; j <= n; j++) {
				if (que[j] == 2) {
					vv.push_back(node[j]);
				}
			}
			if (vv.size() == 0) {
				printf("%d ", ans);
				continue;
			}

			// 离散化处理
			// rule3处理
			if (mis[ct].rule3 != 0) {
				if (mp.find(mis[ct].rule3) != mp.end()) {

					int tmp = func(mis[ct].rule3);

					for (int j = 0; j < app_on_node[tmp].size(); j++) {
						if (que[app_on_node[tmp][j]] == 2) {
							que[app_on_node[tmp][j]] = 3;
						}
					}
//					printf("tmp: ");
//					printf("%d\n", tmp);
//					// 对应运行了 应用mis[ct].rule3 的所有任务区
//					for (int j = 0; j < app_on_area[tmp].size(); j++) {
//						// 任务区下面的所有运算节点
//						for (int k = 0; k < st[app_on_area[tmp][j]].size(); k++) {
//							// 对于rule1,rule2可行的运算节点,如果rule3不可行,设置为3.
//							if (que[st[app_on_area[tmp][j]][k]] == 2) {
//								que[st[app_on_area[tmp][j]][k]] = 3;
//							}
//						}
//					}
				}
			}


			// 排序, 服啦,需要对节点重构
			// 把节点当作结构体
			vector<Node> v;
			v.clear();
			for (int j = 1; j <= n; j++) {
				if (que[j] == 2) {
					v.push_back(node[j]);
				}
			}
			if (v.size() == 0) {
				if (mis[ct].rule3_opt == 0) {
					sort(vv.begin(), vv.end(), cmp);
					ans = vv[0].cnt;
					printf("%d ", ans);
				} else {
					ans = 0;
					printf("%d ", ans);
				}
			} else {
				sort(v.begin(), v.end(), cmp);
				ans = v[0].cnt;
				printf("%d ", ans);
			}

			//cout << "pause" << endl;
			// 维护处理时用到的数据结构 app_on_area
			if (ans != 0) {
				int indx = func(mis[ct].a);
				app_on_area[indx].push_back(node[ans].l);
				app_on_node[indx].push_back(node[ans].cnt);
				node[ans].sz++;
				//printf("%d\n", (int)app_on_area[0][0]);
			}

		}
		printf("\n");
	}

	return 0;
}
posted @ 2022-06-11 19:51  superPG  阅读(51)  评论(0编辑  收藏  举报