HDU-2037 今年暑假不AC 贪心

题目链接 :https://vjudge.net/problem/HDU-2037

题意:

活动安排问题,要求活动之间不能有重叠,问最多能够安排多少活动

分析:

这是经典的活动安排问题

首先可能想到是贪心问题或者动态规划,直觉想到可能是贪心问题。可以想到的可能有三种安排策略:

① 先开始的活动先安排

② 时间短的活动先安排

③ 早结束的活动先安排

第一种策略不正确,举例如下:

a1=<0, 20>, a2=<2, 5>, a3=<8, 15>,如果用这种策略则最多只能安排a1一个活动,但事实上可以安排a2,a3两个活动。

第二种策略也不正确,举例如下:

a1=<0, 8>, a2=<7, 9>, a3=<8, 15>,如果用这种策略最多只能安排a2一个活动,但事实上可以安排a1 ,a3 两个活动。

第三种策略我觉得可以这么思考,假设前k个活动的安排是最优的,那么它一定是结束时间最早的一种安排方法(这样在后面的安排中才会有更多的时间,安排更多的活动),将规模减小至只有一个,即是早结束的活动先安排。下面给出策略正确性的证明:

证明:(对算法步数进行归纳)

(1) 将活动集合按照截止时间递增顺序排列,得到序列S。

(2) 算法第一步选择S中的活动1,设算法最终得到问题最优解为A={i1, i2, …, ij},则i1=1;(算法第一步正确),若i1≠1,用1替换i1,可得到A’=(A-{i1})∪{1},集合A’与A中活动个数相同,且1比i1结束的更早,因此与i2, i3, …, ij相容,于是A’也是问题的一个最优解。

(3) 假设算法前k步正确,令i1=1, i2, …, ik是前k步顺序选择的活动,则原为题最优解可表示为A={i1=1, i2, …, ik}∪B,令S’是S中剩余的与i1, i2, …, ik相容的活动,即S’={j | sj≥fik, j∈S},则B是S’的一个最优解。若不然,假设S’有最优解B’,且|B’| > |B|,那么用B’替换B可以得到的解={i1=1, i2, …, ik} ∪ B’将比A的活动更多,与A为最优解矛盾。

(4) 根据第(2)步,子问题S’存在最优解B*={ik+1, …},则A’={i1=1, i2, …, ik} ∪B*={i1=1, i2, …, ik, ik+1} ∪(B*-{ik+1})为原问题一个最优解,且恰好包含了前k+1步选择的活动。

策略确定之后,就是实现的方法,我的想法是通过自定义结构体并定义优先级(结束时间早的优先级高),再通过优先队列存储节目,最后pop一遍判断可以观看的节目数量。

代码如下:

#include <iostream>
#include <queue>
using namespace std;

struct show {
    int s;
    int f;
    bool operator < (const show& s2) const{
        if(this->f > s2.f) {
            return 1;
        }
        else if(this->f == s2.f){
            return this->s < s2.s;
        }
        else 
            return 0;
    }
};

int main(void) {
    int n;
    while(scanf("%d", &n) == 1 && n != 0) {
        priority_queue <show> q;
        int ans = 0;
        show now;
        now.s = 0, now.f = 0;
        while(n--) {
            show S;
            scanf("%d%d",&S.s, &S.f);
            q.push(S);
        }
//        while(!q.empty()) {
//            printf("%d - %d\n", q.top().s, q.top().f);
//            q.pop();
//        }
        while(!q.empty()) {
            show S = q.top();
            q.pop();
            if(S.s >= now.f) {
                ans++;
                now = S;
            }
        }
        cout << ans << endl;
    }
}
posted @ 2019-04-24 16:24  boobo  阅读(206)  评论(0编辑  收藏  举报
^