活动选择问题(贪心法)

目录

问题概述

实例分析

代码实现


问题概述

实例分析

求解蓄栏保留问题。农场有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;
}

代码结果:

  • 28
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值