• [专题八] 贪心算法


    贪心算法

    区间选点

    /* 给定N个闭区间[ai,bi],请你在数轴上选择尽量少的点,使得每个区间内至少包含一个选出的点。输出选择的点的最小数量。位于区间端点上的点也算作区间内。*/
    const int N = 100010;
    int n;
    struct Range
    {
        int l, r;
        bool operator< (const Range &W)const
        {
            return r < W.r;
        }
    }range[N];
    
    int main()
    {
        scanf("%d", &n);
        for (int i = 0; i < n; i ++ ) scanf("%d%d", &range[i].l, &range[i].r);
        sort(range, range + n);
        int res = 0, ed = -2e9;
        for (int i = 0; i < n; i ++ )
            if (range[i].l > ed)
            {
                res ++ ;
                ed = range[i].r;
            }
        printf("%d
    ", res);
        return 0;
    }
    
    

    最大不相交区间

    /* 给定N个闭区间[ai,bi],请你在数轴上选择若干区间,使得选中的区间之间互不相交(包括端点)。输出可选取区间的最大数量。 */
    const int N = 100010;
    int n;
    struct Range
    {
        int l, r;
        bool operator< (const Range &W)const
        {
            return r < W.r;
        }
    }range[N];
    
    int main()
    {
        scanf("%d", &n);
        for (int i = 0; i < n; i ++ ) scanf("%d%d", &range[i].l, &range[i].r);
        sort(range, range + n);
        int res = 0, ed = -2e9;
        for (int i = 0; i < n; i ++ )
            if (ed < range[i].l)
            {
                res ++ ;
                ed = range[i].r;
            }
        printf("%d
    ", res);
        return 0;
    }
    
    

    区间分组

    /* 给定N个闭区间[ai,bi],请你将这些区间分成若干组,使得每组内部的区间两两之间(包括端点)没有交集,并使得组数尽可能小。*/
    const int N = 100010;
    int n;
    struct Range
    {
        int l, r;
        bool operator< (const Range &W)const
        {
            return l < W.l;
        }
    }range[N];
    
    int main()
    {
        scanf("%d", &n);
        for (int i = 0; i < n; i ++ )
        {
            int l, r;
            scanf("%d%d", &l, &r);
            range[i] = {l, r};
        }
        sort(range, range + n);
        priority_queue<int, vector<int>, greater<int>> heap;
        for (int i = 0; i < n; i ++ )
        {
            auto r = range[i];
            if (heap.empty() || heap.top() >= r.l) heap.push(r.r);
            else
            {
                heap.pop();
                heap.push(r.r);
            }
        }
        printf("%d
    ", heap.size());
        return 0;
    }
    

    区间覆盖

    /*给定N个闭区间[ai,bi]以及一个线段区间[s,t],请你选择尽量少的区间,将指定线段区间完全覆盖。输出最少区间数,如果无法完全覆盖则输出-1。*/
    
    const int N = 100010;
    int n;
    struct Range
    {
        int l, r;
        bool operator< (const Range &W)const {
            return l < W.l;
        }
    }range[N];
    
    int main()
    {
        int st, ed;
        scanf("%d%d", &st, &ed);
        scanf("%d", &n);
        for (int i = 0; i < n; i ++ )
        {
            int l, r;
            scanf("%d%d", &l, &r);
            range[i] = {l, r};
        }
    
        sort(range, range + n);
        int res = 0;
        bool success = false;
        for (int i = 0; i < n; i ++ )
        {
            int j = i, r = -2e9;
            while (j < n && range[j].l <= st) {
                r = max(r, range[j].r);
                j ++ ;
            }
            if (r < st) {
                res = -1;
                break;
            }
            res ++ ;
            if (r >= ed) {
                success = true;
                break;
            }
            st = r;
            i = j - 1;
        }
        if (!success) res = -1;
        printf("%d
    ", res);
        return 0;
    }
    

    排队打水

    /*有 n 个人排队到 1 个水龙头处打水,第 i 个人装满水桶所需的时间是 ti,请问如何安排他们的打水顺序才能使所有人的等待时间之和最小?*/
    typedef long long LL;
    const int N = 100010;
    int n;
    int t[N];
    int main()
    {
        scanf("%d", &n);
        for (int i = 0; i < n; i ++ ) scanf("%d", &t[i]);
    
        sort(t, t + n);
        reverse(t, t + n);
        LL res = 0;
        for (int i = 0; i < n; i ++ ) res += t[i] * i;
        printf("%lld
    ", res);
        return 0;
    }
    

    货仓选址

    /*在一条数轴上有 N 家商店,它们的坐标分别为 A1…AN。A1…AN。现在需要在数轴上建立一家货仓,每天清晨,从货仓到每家商店都要运送一车商品。为了提高效率,求把货仓建在何处,可以使得货仓到每家商店的距离之和最小。*/
    const int N = 100010;
    int n;
    int q[N];
    int main()
    {
        scanf("%d", &n);
        for (int i = 0; i < n; i ++ ) scanf("%d", &q[i]);
        sort(q, q + n);
        int res = 0;
        for (int i = 0; i < n; i ++ ) res += abs(q[i] - q[n / 2]);
        printf("%d
    ", res);
        return 0;
    }
    

    耍杂技的牛

    /*农民约翰的N头奶牛(编号为1..N)计划逃跑并加入马戏团,为此它们决定练习表演杂技。奶牛们不是非常有创意,只提出了一个杂技表演:叠罗汉,表演时,奶牛们站在彼此的身上,形成一个高高的垂直堆叠。
    奶牛们正在试图找到自己在这个堆叠中应该所处的位置顺序。这N头奶牛中的每一头都有着自己的重量Wi以及自己的强壮程度Si。一头牛支撑不住的可能性取决于它头上所有牛的总重量(不包括它自己)减去它的身体强壮程度的值,现在称该数值为风险值,风险值越大,这只牛撑不住的可能性越高。您的任务是确定奶牛的排序,使得所有奶牛的风险值中的最大值尽可能的小。*/
    typedef pair<int, int> PII;
    const int N = 50010;
    int n;
    PII cow[N];
    int main()
    {
        scanf("%d", &n);
        for (int i = 0; i < n; i ++ )
        {
            int s, w;
            scanf("%d%d", &w, &s);
            cow[i] = {w + s, w};
        }
        sort(cow, cow + n);
        int res = -2e9, sum = 0;
        for (int i = 0; i < n; i ++ )
        {
            int s = cow[i].first - cow[i].second, w = cow[i].second;
            res = max(res, sum - s);
            sum += w;
        }
        printf("%d
    ", res);
        return 0;
    }
    

    知识点和代码均学习于Acwing: https://www.acwing.com/activity/

  • 相关阅读:
    无穷有界数列,必有收敛子列(待证)
    有界闭区间内的连续函数必然有界
    数学分析提纲目录
    有限覆盖定理
    函数极限的柯西收敛准则
    数列的柯西收敛准则证明-----华东师大构造数列证明法
    数列柯西收敛准则的子列收敛证明法(取自中科大数分教材)
    用有限覆盖证明闭区间上的连续函数,必然一致连续
    数据库-模糊查询-like关键字-练习
    数据库-基础查询-练习
  • 原文地址:https://www.cnblogs.com/recoverableTi/p/12248061.html
Copyright © 2020-2023  润新知