代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97
| #include <iostream> #include <vector>
using namespace std;
int _count[100][100]; int p[100][100]; int numbers[100]; void dp(int start[], int finish[],int TASK_COUNT) { for (int len = 2; len <= TASK_COUNT + 2; len++) { for (int begin = 0; begin <= TASK_COUNT + 1; begin++) { int end = begin + len - 1; int max = 0; int slice = 0; int k; for (k = begin + 1; k <= end - 1; k++) { if (start[k] >= finish[begin]&&finish[k]<=start[end]) { int temp = _count[begin][k] + _count[k][end] + 1; if (temp > max) { max = temp; slice = k; } } } p[begin][end] = slice; _count[begin][end] = max; } } } void printDp( int begin, int end) { int pos = p[begin][end]; if (pos == 0) return; cout << numbers[pos] << " "; printDp(begin, pos); printDp(pos, end); } int main() { vector<int> vfinish; vector<int> vstart; vstart.push_back(-1); vfinish.push_back(-1); int number; cout << "请分别输入各个事件的开始跟结束时间:" << endl; while (1){ cin >> number; vstart.push_back(number); cin >> number; vfinish.push_back(number); if (cin.get() == '\n') break; } vstart.push_back(255); vfinish.push_back(255); int *start = new int[vstart.size()]; if (!vstart.empty()) memcpy(start, &vstart[0], vstart.size()*sizeof(int)); int *finish = new int[vfinish.size()]; if (!vfinish.empty()) memcpy(finish, &vfinish[0], vfinish.size()*sizeof(int)); int TASK_COUNT = vstart.size()-2; for(int i=0;i<vstart.size();i++) numbers[i]=i; cout << "图例如下:" << endl; for (int i = 0; i <= TASK_COUNT; i++) { cout << i << ":"; for (int j = 0; j < start[i]; j++) { cout << " "; } for (int j = start[i]; j < finish[i]; j++) cout << "■"; cout << endl; } for(int i=0;i<TASK_COUNT+2;i++){ for(int j=0;j<TASK_COUNT+1;j++){ if(finish[j]>finish[j+1]){ std::swap(finish[j],finish[j+1]); std::swap(start[j],start[j+1]); std::swap(numbers[j],numbers[j+1]); } } } for (int i = 0; i <= TASK_COUNT + 2; i++) { for (int j = 0; j <= TASK_COUNT + 2; j++) { _count[i][j] = 0; p[i][j] = 0; } } dp(start, finish, TASK_COUNT); cout << "总共可完成的事件个数为:" << _count[0][TASK_COUNT + 1] << endl; cout << "完成的事件为:"; printDp(0, TASK_COUNT + 1); return 0; }
|
总结:
区间调度的实验采用了结束时间先后为顺序排序。按照排序依次比较看事件是否匹配,如果匹配则加入。贪心算法,优先选择最早结束的需求,确保资源尽可能早地被释放,把留下来满足其他需求的时间最大化。具体伪代码如下所示,算法结束后集合A中会保留所有相容请求,A的大小即是最大相容数量。Aijj为Sij最优解,另其中的任务按照结束时间递增排序,令ak是Aij的第一个结束的任务,如果ak=am,则证明成立。否则我们将ak用am替换,则它成为了另一个解A’ij,同样是最优解。所以即将任务以结束时间递增排序,第一个结束的任务一定在最优解中,依次找出子问题中最先结束,且开始时间在前一个解最后一个任务结束之间之后。复杂度为O(n)。同时很容易得出有递归和递推两种形式,一般采用递推。