贪心算法经典问题

目录

贪心思想

一、Dijkstra最短路问题

问题描述:

贪心策略:

[二、Prim 和 Kruskal 最小生成树问题](#二、Prim 和 Kruskal 最小生成树问题)

[Prim 算法:](#Prim 算法:)

[Kruskal 算法:](#Kruskal 算法:)

三、Huffman树问题

问题描述:

贪心策略:

四、背包问题

问题描述:

贪心策略:

五、硬币找零问题

问题描述:

贪心策略:

六、区间合并问题

问题描述:

贪心策略:

七、选择不相交区间问题

问题描述:

贪心策略:

八、区间选点问题

问题描述

贪心策略

九、区间覆盖问题

问题描述:

贪心策略:

十、区间分组问题

问题描述:

贪心策略:

十一、任务调度问题

问题描述:

贪心策略:

十二、加油站问题

问题描述:

贪心策略:

十三、跳跃游戏

问题描述:

贪心策略:

[十四、跳跃游戏 II](#十四、跳跃游戏 II)

问题描述:

贪心策略:

十五、股票买卖问题

问题描述:

贪心策略:

十六、最小代价贪心问题

问题描述:

贪心策略:

1.https://codeforces.com/contest/2118/problem/C

思路:

代码:

2.https://codeforces.com/contest/1722/problem/D

思路:

代码:

十七、其他

1.B-黄_牛客小白月赛118

思路:

代码:

2.https://codeforces.com/problemset/problem/2116/B

思路及代码:cf2116B-CSDN博客

3.https://codeforces.com/problemset/problem/2067/B

思路及代码:cf2067B-CSDN博客

4.https://codeforces.com/problemset/problem/2059/B

思路及代码:cf2059B-CSDN博客

5.https://codeforces.com/contest/1760/problem/E

思路:

代码:


贪心思想

贪心算法(Greedy Algorithm)是一种在求解问题时,每一步都选择当前最优解,以期望最终得到全局最优解的算法思想。贪心算法的基本思想可以总结为"每一步都做出一个局部最优的选择,最终就能得到全局最优解"。

一、Dijkstra最短路问题

问题描述:

在一个图中,找到从起点到其他所有点的最短路径(适用于无负边权的情况)。

贪心策略:

每次扩展离源点最近的未访问节点。

二、Prim 和 Kruskal 最小生成树问题

Prim 算法:

从任意一个顶点开始,逐步加入与当前树连接权重最小的边。

Kruskal 算法:

按边权从小到大排序,依次加入不会形成环的边。

三、Huffman树问题

问题描述:

构造一个带权路径长度最小的二叉树,用于数据压缩中的最优前缀编码。

贪心策略:

每次合并两个频率最小的节点。

四、背包问题

问题描述:

物品可以取部分,目标是在容量限制下最大化总价值。

贪心策略:

按单位重量价值从高到低依次选取。

五、硬币找零问题

问题描述:

给定不同面值的硬币,求最少数量凑出某个金额。

贪心策略:

优先使用最大面值的硬币。

六、区间合并问题

问题描述:

给定多个区间,合并所有有重叠或相邻的区间,返回合并后的无重叠区间列表。

贪心策略:

按左端点排序后依次处理,若当前区间与结果中最后一个区间重叠,则合并。

七、选择不相交区间问题

问题描述:

给定多个时间区间,从中选择尽可能多的互不重叠的区间。

贪心策略:

按右端点从小到大排序,每次选择最早结束的区间,跳过与其冲突的区间。

八、区间选点问题

问题描述

在每个区间中至少选一个点,使得这些点覆盖所有区间,要求所选点的数量最少。

贪心策略

按右端点排序,每次在当前未被覆盖的区间的右端点上选一个点。

九、区间覆盖问题

问题描述:

给定一个目标区间和若干子区间,判断是否能用这些子区间完全覆盖目标区间。

贪心策略:

按左端点排序,从起点开始,每次选择能延伸最远的区间,逐步扩展覆盖范围。

十、区间分组问题

问题描述:

将一组区间分成若干个组,每组内的区间互不重叠,要求使用的组数最少。

贪心策略:

按左端点排序,使用最小堆维护各组的最早可用时间,优先将当前区间分配给最早空闲的组。

十一、任务调度问题

问题描述:

给定若干任务及其完成期限和利润,选择能获得最大利润的任务序列。

贪心策略:

按利润降序排序,依次尝试安排任务在最后可行的时间点。

十二、加油站问题

问题描述:

一辆车绕一圈油路,判断是否可以从某一点出发完成一圈,并找出该起点。

贪心策略:

维护当前油量和总油量,若当前油量为负则重新设置起点。

十三、跳跃游戏

问题描述:

数组中每个元素代表可跳跃的最大步数,判断是否可以到达最后一个位置。

贪心策略:

维护当前能跳到的最远位置,逐步推进。

十四、跳跃游戏 II

问题描述:

在跳跃游戏中,求最少跳跃次数到达终点。

贪心策略:

维护当前能跳的最远边界,以及下一步的最远可达。

十五、股票买卖问题

问题描述:

允许多次买卖,但每次只能持有一股。

贪心策略:

只要第二天价格比今天高,就买入卖出。

十六、最小代价贪心问题

问题描述:

在有限操作次数内,通过优先选择代价最低的操作使目标值最大化。

贪心策略:

按操作代价从小到大依次选择操作,直到操作次数用尽。

1.https://codeforces.com/contest/2118/problem/C

思路:

统计每个数字每一位变1的代价,排序取最小的 n 个即可。

代码:
cpp 复制代码
void solve()
{
    ll n, k;
    cin >> n >> k;
    vector<ll> a(n + 10);
    cin >> a;

    vector<ll> v;
    ll ans = 0;
    for (ll i = 0; i < n; ++i)
    {
        ll x = a[i];
        ll cnt = 0;
        for (ll j = 0; j < 63; ++j)
        {
            if (x >> j & 1ll)
                ans++;
            else
                v.pb(1ll << j);
        }
    }

    sort(all(v));
    for (auto x : v)
    {
        if (k <= 0)
            break;
        if (k >= x)
        {
            ans++;
            k -= x;
        }
    }

    cout << ans << endl;
}

2.https://codeforces.com/contest/1722/problem/D

思路:

统计每个字符最大贡献与当前贡献的差值,排序即可。

代码:
cpp 复制代码
void solve()
{
    int n;
    string s;
    cin >> n >> s;
    s = ' ' + s;

    ll ans = 0;
    vector<int> maxx(n + 10, 0);
    for (int i = 1; i <= n; ++i)
    {
        if (s[i] == 'L')
        {
            maxx[i] = {abs(max(i - 1, (n - i)) - (i - 1))};
            ans += i - 1;
        }
        else
        {
            maxx[i] = {abs(max(i - 1, (n - i)) - (n - i))};
            ans += n - i;
        }
    }

    sort(maxx.begin() + 1, maxx.begin() + 1 + n, greater<int>());

    for (int i = 1; i <= n; ++i)
    {
        ans += maxx[i];
        cout << ans << ' ';
    }
    cout << endl;
}

十七、其他

这类题目不是经典的贪心模型,但是解题思路是基于贪心策略的题目。

1.B-黄_牛客小白月赛118

思路:

每次配对 a[i] 和 a[i + 1],如果不互质,就将 a[i + 1] 变为 1,因为 a[i] 在之前可能与其他的元素配对了,选择修改 a[i + 1] 是更优的。

代码:
cpp 复制代码
void solve()
{
    int n;
    cin >> n;
    vector<ll> a(n + 10);
    for (int i = 0; i < n; ++i)
        cin >> a[i];

    ll ans = 0;
    for (int i = 0; i < n - 1; ++i)
    {
        if (__gcd(a[i], a[i + 1]) != 1)
        {
            a[i + 1] = 1;
            ++ans;
        }
    }

    cout << ans << endl;
}

2.https://codeforces.com/problemset/problem/2116/B

思路及代码:cf2116B-CSDN博客

3.https://codeforces.com/problemset/problem/2067/B

思路及代码:cf2067B-CSDN博客

4.https://codeforces.com/problemset/problem/2059/B

思路及代码:cf2059B-CSDN博客

5.https://codeforces.com/contest/1760/problem/E

思路:

题目要求统计 的索引对数,由于只有 0、1 两种元素,所以只需统计 1 后面有几个 0 即可;我们还可以将 1 个元素取反,不难发现将第一个值为 0 的元素变 1 或最后一个值为1 的元素变 0 贡献最大,可证明该贪心策略成立,由于数据量不大,直接把三种情况都统计一遍即可(不变的也要统计)。

代码:
cpp 复制代码
void solve()
{
    int n;
    cin >> n;
    vi a(n + 10), b;
    cin >> a;

    vi cnt1(n + 10, 0);
    int cur = 0;
    for (int i = n - 1; ~i; --i)
        if (a[i] == 0)
            ++cur;
        else
            cnt1[i] = cur;

    b = a;
    for (int i = 0; i < n; ++i)
        if (b[i] == 0)
        {
            b[i] = 1;
            break;
        }

    vi cnt2(n + 10, 0);
    cur = 0;
    for (int i = n - 1; ~i; --i)
        if (b[i] == 0)
            ++cur;
        else
            cnt2[i] = cur;

    b = a;
    for (int i = n - 1; ~i; --i)
        if (b[i] == 1)
        {
            b[i] = 0;
            break;
        }

    vi cnt3(n + 10, 0);
    cur = 0;
    for (int i = n - 1; ~i; --i)
        if (b[i] == 0)
            ++cur;
        else
            cnt3[i] = cur;

    ll ans1 = 0, ans2 = 0, ans3 = 0;
    for (int i = 0; i < n; ++i)
        ans1 += cnt1[i];
    for (int i = 0; i < n; ++i)
        ans2 += cnt2[i];
    for (int i = 0; i < n; ++i)
        ans3 += cnt3[i];

    cout << max({ans1, ans2, ans3}) << endl;
}
相关推荐
tan180°3 小时前
MySQL表的操作(3)
linux·数据库·c++·vscode·后端·mysql
大千AI助手3 小时前
DTW模版匹配:弹性对齐的时间序列相似度度量算法
人工智能·算法·机器学习·数据挖掘·模版匹配·dtw模版匹配
彭祥.4 小时前
Jetson边缘计算主板:Ubuntu 环境配置 CUDA 与 cudNN 推理环境 + OpenCV 与 C++ 进行目标分类
c++·opencv·分类
lzb_kkk4 小时前
【C++】C++四种类型转换操作符详解
开发语言·c++·windows·1024程序员节
YuTaoShao5 小时前
【LeetCode 热题 100】48. 旋转图像——转置+水平翻转
java·算法·leetcode·职场和发展
生态遥感监测笔记5 小时前
GEE利用已有土地利用数据选取样本点并进行分类
人工智能·算法·机器学习·分类·数据挖掘
Tony沈哲5 小时前
macOS 上为 Compose Desktop 构建跨架构图像处理 dylib:OpenCV + libraw + libheif 实践指南
opencv·算法
刘海东刘海东6 小时前
结构型智能科技的关键可行性——信息型智能向结构型智能的转变(修改提纲)
人工智能·算法·机器学习
胖大和尚6 小时前
clang 编译器怎么查看在编译过程中做了哪些优化
c++·clang