zoukankan      html  css  js  c++  java
  • [啃书] 第7篇

    前言

    接着第四章

    本篇总结自《算法笔记》4.4 贪心

    正文

    知识点1:简单贪心

    贪心是只考虑当下的一种局部最优(或较优),来使全局结果达到最优(或较优)的策略。

    证明策略是最优(或较优)的:反证法、数学归纳法【证明较复杂,若有不错的思路且无法找到反例,直接实现即可】

    例1  PAT B1020(卖月饼P118)

    #include<cstdio>
    #include<algorithm>
    using namespace std;
    
    struct mooncake { // 结构体整合输入数据
        double store; // 库存
        double sell; // 总价
        double price; // 单价(库存除总价)
    }cake[1010];
    
    bool cmp(mooncake a, mooncake b) {
        return a.price > b.price;
    }
    
    int main() {
        int n; // 月饼种类数
        double D; // 月饼需求量
        scanf("%d%lf", &n, &D);
        for(int i = 0; i < n; i++) { // 输入库存
            scanf("%lf", &cake[i].store);
        }
        for(int i = 0; i < n; i++) { // 输入总价 并计算单价
            scanf("%lf", &cake[i].sell);
            cake[i].price = cake[i].sell / cake[i].store;
        }
        sort(cake, cake + n, cmp); // 按单价从高到低排序
        double ans = 0; // 收益
        for(int i = 0; i < n; i++) { // 遍历排序后的月饼列表cake
            if(D >= cake[i].store) { // 需求大于供应
                D -= cake[i].store;
                ans += cake[i].sell; // 该类月饼全部卖出
            } else { // 需求小于供应
                ans += cake[i].price * D; // 需求全部满足
                break;
            }
        }
        printf("%.2f
    ", ans);
        return 0;
    }

    只在乎销售额,只要每次选最贵的就能达到总销售额最多(贪心)。

    例2  PAT B1023(组个最小数)

    #include<cstdio>
    
    int main() {
        int count[10]; // 记录数字0~9的个数
        for(int i = 0; i < 10; i++) {
            scanf("%d", count + i); // 录入0~9各数字个数
        }
        for(int i = 1; i < 10; i++) {
            if(count[i] > 0) {
                printf("%d", i); // 输出除0外最小的数作为最高位
                count[i]--;
                break;
            }
        }
        for(int i = 0; i < 10; i++) {
            for(int j = 0; j < count[i]; j++) { // 把i输出count[i]次
                printf("%d", i);
            }
        }
        return 0;
    }

    只要每次都拿最小的数放在最高位,最后组成的数必然最小(贪心)。

    知识点2:区间贪心(给出若干小区间,看最多能塞多少个)

    #include<cstdio>
    #include<algorithm>
    using namespace std;
    const int maxn = 110;
    struct Interval{
        int x, y;
    }I[maxn];
    
    bool cmp(Interval a, Interval b) {
        if(a.x != b.x) return a.x > b.x; // 左端点从大到小
        else return a.y < b.y; // 左端点相同时,右端点从小到大(写b.y > a.y容易理解错)
    }
    
    int main() {
        int n;
        while(scanf("%d", &n), n != 0) { // 输入提供选择的区间个数
            for (int i = 0; i < n; i++)
            {
                scanf("%d%d", &I[i].x, &I[i].y); // 顺序输入区间的左右端点
            }
            sort(I, I + n, cmp); // 把区间排序
            int ans = 1, lastX = I[0].x; // ans记录不相交区间数,lastX记录上一个被选区间的左端点
            for(int i = 1; i < n; i++) {
                if(I[i].y <= lastX) { // 若该区间右端点在lastX左边
                    lastX = I[i].x; // 以I[i]作为新选中的区间
                    ans++; // 区间数++
                }
            }
            printf("%d
    ", ans);
        }
        return 0;
    }

    稍微复杂的贪心策略:如下图两种情况按下标顺序选取

    博主ChaosBlog原创,搬运请注明。
    个人博客地址 cnblogs.com/cc1997;
    个人网站地址 Ccoding.cn
  • 相关阅读:
    Kubernetes 查看node
    Zookeeper ZAB 协议分析[转]
    zookeeper 快速入门
    Kubernetes-dns 域名解析问题
    Kubernetes-dns 服务搭建
    Kubernetes dashboard 配置
    kubernetes 入门学习
    使用jenkins SonarQube gitlab 构建自动化发布系统
    VMware Harbor 学习
    docker快速入门
  • 原文地址:https://www.cnblogs.com/cc1997/p/14915103.html
Copyright © 2011-2022 走看看