目录
问题概述
实例分析
代码实现
问题概述
实例分析
求解蓄栏保留问题。农场有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;
else
return 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;
}
代码结果: