201403-5 任务调度 解题策略探讨

点击前往试题目录:https://blog.csdn.net/best335/article/details/99550556在这里插入图片描述

如果你确实想解出题,你可以搜索 KD-Tree、三维偏序、CDQ分治 。

我的思路:这道题需要你不断地减少搜索范围也就是剪枝。
**或者想象使两个CPU设备差值最小的背包问题,这很难建模 **

  • 定义:
  • C(使用一个CPU所用的时间)
  • G (使用一个CPU和一个GPU所用的时间)
  • CC(使用两个CPU或全部使用的最小值)

剪枝策略

  • 同时使用两个CPU和使用全部设备是等价的,我们只需要取最小值。
  • 对于min(C,G)<=CC的任务,我们只执行C或G
    • 若C<=G,仅执行C
    • 若C > G,执行C,G
      • 对于sum( C )>sum( G )的只执行G
      • 否则执行C,G,这里还可以优化。
  • 对于min(C,G)>CC的任意两个任务
    • 若min(C1,G1)+min(C2,G2)<=(CC1+CC2)/2+(CC1+CC2)%1,我们只执行他们的C或G。
    • 否则我们执行C、G、CC
  • 我们使用集合来最大限度的减少重复计算。
    • 我们使用这样的排序策略:
      • struct P{
        int a,b,c,d;
        bool operator < (const& P p)const{return a<p.a&&b<p.b&&c<p.c&&d<p.d;}
        }
        set< P > S;
      • 对于集合中任意两个对象p1,p2我们只是用p1!<p2的p1,用来优化插入的只有KD-tree了
  • 我们限制两个CPU使用时的差距不得超过 10*剩余的任务数
大概三分钟可以求出解
其中插入时间复杂度为O(n^3)
解题策略为分治+剪枝+插入优化
#pragma GCC optimize(2)
#include<iostream>
#include<unordered_set>
#define DEBUG
#ifdef DEBUG
#include<fstream>
#include<ctime>
#include<windows.h>
#endif
using namespace std;
inline int _abs(const int&a) {
	return a<0 ? -a : a;
}

struct Task {
	int C1, C2, G1, G2;
	Task(const int& C1_, const int& C2_, const int& G1_, const int& G2_) :C1(C1_), C2(C2_), G1(G1_), G2(G2_) {
		if (C1>C2) swap(C1, C2), swap(G1, G2);
	}
};
inline bool operator==(const Task &t1, const Task &t2) {
	return t1.C1 == t2.C1&&t1.C2 == t2.C2&&t1.G1 == t2.G1&&t1.G2 == t2.G2;
}
inline bool operator <(const Task& t1, const Task& t2) {
	return t1.C1 <= t2.C1&&t1.C2 <= t2.C2&&t1.G1 <= t2.G1&&t1.G2 <= t2.G2;
}
struct Hasher {
	size_t operator()(const Task &t) const noexcept {
		return std::hash<long long>{}(t.C1 + t.C2 * 400L + t.G1 * 160000L + t.G2 * 64000000L);
	}
};
struct Comparator {
	bool operator()(const Task &t1, const Task &t2) const noexcept {
		return t1.C1 == t2.C1&&t1.C2 == t2.C2&&t1.G1 == t2.G1&&t1.G2 == t2.G2;
	}
};
unordered_set<Task, Hasher, Comparator> T[41];
int main() {
	int n, ans = 400, H;
#ifdef DEBUG
	ifstream cin("C:\\Users\\Isidore\\Desktop\\out.txt");
	clock_t t1 = clock();
#endif
	cin >> n, H = n * 10 + 1;
	for (int i = 0, a, b, c, d, e, f; i<n; ++i) {
		cin >> a >> b >> c >> d, e = min(a, c), f = min(b, d);//C > CG > CC = CCG  优先级
		T[i].insert(Task(0, a, 0, 0));
		if (f<e) T[i].insert(Task(f, f, b>d ? d : 0, b>d ? d : 0));
		else if (c<a) T[i].insert(Task(0, c, 0, c));
	}
	for (short int i = 2, xi = 1; !T[xi].empty(); xi = i, i += i) {
		for (short int j = 0, nj = min(40, n + xi); j + xi<nj; j += i) {
			unordered_set<Task, Hasher, Comparator> List, &curr1 = T[j], &curr2 = T[j + xi];
			cout << j <<" "<< j + xi<<" "<< curr1.size()<<" "<<curr2.size()<<" | ";
			if (!curr1.empty() && !curr2.empty()) {
				H -= 10;
				for (const Task&t1 : curr1)
					for (const Task&t2 : curr2) {
						unordered_set<Task, Hasher, Comparator> proc;
						if (_abs(t1.C1 + t2.C1 - t1.C2 - t2.C2)<H)
							proc.insert(Task(t1.C1 + t2.C1, t1.C2 + t2.C2, t1.G1 + t2.G1, t1.G2 + t2.G2));
						if (_abs(t1.C1 + t2.C2 - t1.C2 - t2.C1)<H) 
							proc.insert(Task(t1.C1 + t2.C2, t1.C2 + t2.C1, t1.G1 + t2.G2, t1.G2 + t2.G1));
						for (auto itList = List.begin(); itList != List.end() && !proc.empty();) {
							const Task & list = *itList;
							bool F = true;
							for (auto itCurr = proc.begin(); itCurr != proc.end();) {
								const Task& curr = *itCurr;
								if (list == curr || list<curr) proc.erase(itCurr++);
								else if (curr<list) {
									List.erase(itList++), F = false;
									break;
								}
								else ++itCurr;
							}
							if (F) ++itList;
						}
						List.insert(proc.begin(), proc.end());
					}
			}
			if(!List.empty()) T[j].swap(List);
			curr2.clear();
		}
		cout << endl;
	}
	for (const Task&t : T[0]) ans = min(ans, max(max(t.C1, t.C2), t.G1 + t.G2));
	cout << ans << endl;
#ifdef DEBUG
	clock_t t2 = clock();
	cout << T[n].size() << " " << t2 - t1 << "ms" << endl;
	system("pause");
#endif
	return 0;
}
发布了107 篇原创文章 · 获赞 21 · 访问量 3万+

猜你喜欢

转载自blog.csdn.net/best335/article/details/98772750
今日推荐