目录
问题概述
实例分析
代码实现
问题概述
实例分析
求解蓄栏保留问题。农场有n头牛,每头牛会有一个特定的时间区间[b,e]在蓄栏里挤牛奶,并且一个蓄栏里任何时刻只能有一头牛挤奶。现在农场主希望知道最少蓄栏能够满足上述要求,并给出每头牛被安排的方案。对于多种可行方案,输出一种即可。
解:牛的编号为1~n,每头牛的挤奶时间相当于一个活动,与前面活动安排问题不同,前面的活动时间是半闭区间,而这里的活动时间是闭区间,例如这里[2,4]与[4,7]是交叉的,它们不是兼容活动。
采用与求解活动安排问题类似的贪心思路,将所有活动这样排序:
结束时间相同按开始时间递增排序,否则按结束时间递增排序。求出一个最大兼容活动子集,将它们安排在一个蓄栏中(蓄栏编号为1);如果没有安排完,再在剩余的活动再求下一个最大兼容活动子集,将它们安排在另一个蓄栏中(蓄栏编号为2),以此类推。也就是说,最大兼容活动子集的个数就是最少蓄栏个数。
代码实现
#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;const int MAX = 6;struct Cow {int no;int b;int e;bool operator<(const Cow &s) const {if (e == s.e)return b <= s.b;elsereturn e <= s.e;}
};Cow A[MAX] = {{0},{1,1,10},{2,2,4},{3,3,6},{4,5,8},{5,4,7}};int ans[MAX];void solve() {sort(A + 1, A + MAX);memset(ans, 0, sizeof(ans));int num = 1;for (int i = 1; i <= MAX; i++) {if (ans[i] == 0) {ans[i] = num;int preend = A[i].e;for (int j = i + 1; j <= MAX; j++) {if (A[j].b > preend && ans[j] == 0) {ans[j] = num;preend = A[j].e;}}num++;}}
}int main() {solve();cout << "ret" << endl;for (int i=1; i<=MAX; i++){printf("Cow%d: %d\n", A[i].no, ans[i]);}return 0;
}
代码结果: