• 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
    ", 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;
        }
    }
  • 相关阅读:
    for循环实战性能优化
    MySQL group_concat 介绍
    MySQL 取分组后每组的最新记录
    MySQL查询top N记录
    常用SQL之日期格式化和查询重复数据
    Java 8 ThreadLocal 源码解析
    避免创建不必要的对象
    IntelliJ IDEA 设置忽略SVN文件和文件夹
    scrapy+selenium+chromedriver解析动态渲染页面
    java读取excel或者csv时日期格式数据处理
  • 原文地址:https://www.cnblogs.com/RB26DETT/p/10732649.html
Copyright © 2020-2023  润新知