算法基础篇:(八)贪心算法之简单贪心:从直觉到逻辑的实战指南

目录

前言

[一、贪心算法是什么?------ 不止是 "鼠目寸光"](#一、贪心算法是什么?—— 不止是 “鼠目寸光”)

[1.1 贪心的核心思想](#1.1 贪心的核心思想)

[1.2 贪心算法的三大特点](#1.2 贪心算法的三大特点)

[1.3 学习贪心的正确姿势](#1.3 学习贪心的正确姿势)

[二、经典例题实战 ------ 简单贪心的 5 个核心场景](#二、经典例题实战 —— 简单贪心的 5 个核心场景)

[例题 1:货仓选址(洛谷 P10452)------ 中位数的魔力](#例题 1:货仓选址(洛谷 P10452)—— 中位数的魔力)

题目描述

题目分析

贪心策略

逻辑证明(反证法)

代码实现

拓展结论

[例题 2:最大子段和(洛谷 P1115)------ 果断舍弃 "负资产"](#例题 2:最大子段和(洛谷 P1115)—— 果断舍弃 “负资产”)

题目描述

题目分析

贪心策略

逻辑证明(反证法)

代码实现

注意点

[例题 3:纪念品分组(洛谷 P1094)------ 双指针的 "配对艺术"](#例题 3:纪念品分组(洛谷 P1094)—— 双指针的 “配对艺术”)

题目描述

题目分析

贪心策略

逻辑证明(交换论证法)

代码实现

优化点

[例题 4:排座椅(洛谷 P1056)------ 贪心的 "优先级选择"](#例题 4:排座椅(洛谷 P1056)—— 贪心的 “优先级选择”)

题目描述

题目分析

贪心策略

逻辑证明

代码实现

注意点

[例题 5:矩阵消除游戏(牛客网)------ 贪心 + 枚举的 "组合拳"](#例题 5:矩阵消除游戏(牛客网)—— 贪心 + 枚举的 “组合拳”)

题目描述

题目分析

贪心策略

逻辑证明

代码实现

优化点

三、简单贪心的常见策略总结

[1. 排序 + 选择类](#1. 排序 + 选择类)

[2. 收益最大化类](#2. 收益最大化类)

[3. 舍弃负资产类](#3. 舍弃负资产类)

[4. 枚举 + 贪心类](#4. 枚举 + 贪心类)

四、贪心算法的常见误区与避坑指南

[1. 误区 1:认为 "贪心就是选最大 / 最小"](#1. 误区 1:认为 “贪心就是选最大 / 最小”)

[2. 误区 2:不证明策略正确性,直接编码](#2. 误区 2:不证明策略正确性,直接编码)

[3. 误区 3:忽视边界情况](#3. 误区 3:忽视边界情况)

[4. 避坑指南](#4. 避坑指南)

总结


前言

在算法的世界里,有一类算法如同生活中的 "即时决策派"------ 不纠结于未来的所有可能性,只专注于当下的最优选择,这就是贪心算法。它看似简单直观,甚至有些 "鲁莽",却能高效解决一大批经典问题。但贪心算法也是出了名的 "两极分化":简单题能让你觉得 "理所当然",难题却能让你怀疑人生。今天我们就聚焦贪心算法的入门核心 ------ 简单贪心,通过经典例题拆解其思想、逻辑证明和代码实现,帮你从 "知其然" 到 "知其所以然",真正掌握这份 "当下最优" 的智慧。下面就让我们正式开始吧!


一、贪心算法是什么?------ 不止是 "鼠目寸光"

1.1 贪心的核心思想

贪心算法,本质上是一种 "局部最优导向全局最优" 的策略。它将复杂问题拆分成一系列连续的子问题,在每个子问题中都做出当前看起来最优的选择,并且不回溯、不反悔,最终希望通过这些局部最优解的累积得到全局最优解。

举个生活中的例子:你要从家到公司,想最快到达。贪心策略就是:每个路口都选择当前路况最好、距离最近的路线,而不是提前规划全程所有可能路径 ------ 这种 "走一步看一步" 的决策方式,正是贪心的核心。

但这里有个关键前提:并非所有问题都能用贪心解决 。只有当问题满足 "局部最优解的累积必然导致全局最优解" 时,贪心才有效。这也是贪心算法的难点所在:策略的提出不难,难的是证明它是正确的

1.2 贪心算法的三大特点

  1. 无后效性:每个子问题的决策只依赖当前状态,不影响之前的决策,也不被之前的决策所影响。
  2. 贪心选择性质:全局最优解可以通过一系列局部最优解(贪心选择)得到。
  3. 无固定模板:与动态规划有明确的状态转移方程不同,贪心策略需要根据具体问题场景设计,没有通用的套路可循。

1.3 学习贪心的正确姿势

很多初学者会有困惑:为什么做了几十道贪心题,遇到新题还是没思路?其实这是正常现象!贪心的灵活性决定了它需要大量的题型积累和逻辑训练。学习时要注意以下几点:

  • 前期重点吸收各种题型的贪心策略,把它们当成 "经验库";
  • 尽量尝试证明策略的正确性(常用反证法、数学归纳法、交换论证法),培养严谨思维;
  • 比赛中无需过度纠结证明:如果策略能通过几个边界情况,就可以大胆尝试编码。

二、经典例题实战 ------ 简单贪心的 5 个核心场景

下面我们通过 5 道经典例题,拆解简单贪心的常见场景、策略设计和代码实现。每道题都会从**"题目分析→贪心策略→逻辑证明→代码实现"**四个维度展开,帮你吃透核心逻辑。

例题 1:货仓选址(洛谷 P10452)------ 中位数的魔力

题目链接: https://www.luogu.com.cn/problem/P10452

题目描述

在一条数轴上有 n 家商店,坐标分别为 a₁, a₂, ..., aₙ。现在要在数轴上建立一家货仓,求货仓建在何处,能使货仓到所有商店的距离之和最小。

输入:第一行 n,第二行 n 个整数表示商店坐标(n≤1e5,aᵢ≤1e6)

输出:距离之和的最小值

示例输入:46 2 9 1

示例输出:12

题目分析

这是一道典型的**"一维选址"** 问题。直观上,我们可能会想到 "平均值" ------ 毕竟平均值是数据的中心。但实际上,中位数才是最优解。为什么?

贪心策略

  1. 将所有商店坐标从小到大排序;
  2. 货仓建在中位数 位置:
    • 若 n 为奇数,选第 (n+1)/2 个位置;
    • 若 n 为偶数,选第 n/2 到第 n/2+1 个位置之间的任意点(距离和相同)。

逻辑证明(反证法)

假设货仓建在非中位数位置 x,中位数为 m。我们证明将 x 移到 m 会使距离和减小:

设排序后的坐标为a₁≤a₂≤...≤aₙ,中位数 m=a [k](k=(n+1)/2)

  • x>m:此时在 m 左侧有 k 家商店,右侧有 n-k 家商店(n-k≤k)。将 x 向左移动 1 单位,左侧商店的总距离增加 1×k,右侧商店的总距离减少 1×(n-k),总距离变化为 k-(n-k)=2k-n≥0(因为 k≥n/2),即总距离减小或不变
  • x<m:同理,将 x 向右移动 1 单位,总距离会减小或不变

因此,只有当 x=m 时,距离和达到最小值

代码实现

cpp 复制代码
#include <iostream>
#include <algorithm>
using namespace std;

typedef long long LL;
const int N = 1e5 + 10;
int n;
LL a[N];

int main() {
    cin >> n;
    for (int i = 1; i <= n; i++) cin >> a[i];
    sort(a + 1, a + 1 + n);
    
    LL ret = 0;
    // 利用结论计算:(a[n]-a[1]) + (a[n-1]-a[2]) + ... 
    for (int i = 1; i <= n / 2; i++) {
        ret += a[n - i + 1] - a[i];
    }
    
    cout << ret << endl;
    return 0;
}

拓展结论

对于公式 (i=1 到 n),当 x 取数组的中位数时,sum 取得最小值。这个结论在后续的贪心、动态规划问题中会频繁用到,一定要牢记!

例题 2:最大子段和(洛谷 P1115)------ 果断舍弃 "负资产"

题目链接: https://www.luogu.com.cn/problem/P1115

题目描述

给出一个长度为 n 的序列 a,选出其中连续且非空的一段,使得这段的和最大。

输入:第一行 n,第二行 n 个整数(1≤n≤2e5,-1e4≤aᵢ≤1e4)

输出:最大子段和

示例输入:72 -4 3 -1 2 -4 3

示例输出:4(对应子段 [3,-1,2])

题目分析

这道题是贪心算法的经典应用,也是面试高频题。核心矛盾是:当当前累积和为负数时,是否要舍弃前面的子段?

贪心策略

从前往后遍历序列,维护一个当前累积和 sum和最大子段和 ret

  1. 每次将当前元素加入 sum;
  2. 更新 ret 为 ret 和 sum 中的较大值
  3. sum<0:说明当前子段对后续累加毫无贡献(甚至会拖后腿),直接将 sum 重置为 0,从下一个元素重新开始累积。

逻辑证明(反证法)

我们需要证明:当sum<0 时,舍弃当前子段是最优选择。

假设存在一段区间 [a,b],其和 sum [a,b]<0。若不舍弃这段区间,后续存在子段 [b+1,c],使得 sum [a,c] 是最大子段和。但sum [a,c] = sum [a,b] + sum [b+1,c] < sum [b+1,c],这与 sum [a,c] 是最大子段和矛盾。因此,舍弃 sum<0 的子段不会错过最优解。

进一步证明:区间内不存在比当前起点更优的起点。假设区间 [a,b] 中存在点 c(a<c≤b),使得 sum [c,b] 是更优的起点。则 sum [a,c-1] = sum [a,b] - sum [c,b] < 0,这与贪心策略中 "sum≥0 时才继续累积" 的逻辑矛盾 ------ 因为如果 sum [a,c-1]<0,我们早就在 c 点重新开始累积了。因此,当前起点是最优的。

代码实现

cpp 复制代码
#include <iostream>
using namespace std;

typedef long long LL;
const int N = 2e5 + 10;
int n;
LL a[N];

int main() {
    cin >> n;
    for (int i = 1; i <= n; i++) cin >> a[i];
    
    LL sum = 0, ret = -1e6; // ret初始化为最小值,应对全负序列
    for (int i = 1; i <= n; i++) {
        sum += a[i];
        ret = max(ret, sum);
        if (sum < 0) sum = 0; // 舍弃负资产
    }
    
    cout << ret << endl;
    return 0;
}

注意点

  • 初始时 ret 要设为极小值(如 - 1e6),而不是 0------ 因为序列可能全为负数,此时最大子段和是最大的那个负数。
  • 时间复杂度O (n) ,空间复杂度 O (1),是该问题的最优解法。

例题 3:纪念品分组(洛谷 P1094)------ 双指针的 "配对艺术"

题目链接: https://www.luogu.com.cn/problem/P1094

题目描述

元旦晚会要发放纪念品,每组最多 2 件,且每组总价格不超过 w。求最少的分组数目。

输入:第一行 w(每组价格上限),第二行 n(纪念品总数),后续 n 行是每件纪念品的价格(1≤n≤3e4,80≤w≤200,5≤pᵢ≤w)

输出:最少分组数

示例输入:1009902020305060708090示例输出:6

题目分析

要使分组数最少,核心思路是 "尽可能让每件纪念品都和其他纪念品配对",避免单独分组。最优策略是让 "最便宜的和最贵的配对"------ 如果两者之和不超过 w,就配对;否则最贵的只能单独分组(因为它无法和任何其他纪念品配对)。

贪心策略

  1. 将所有纪念品价格从小到大排序;
  2. 用双指针 l(指向当前最便宜的 )和 r(指向当前最贵的);
  3. a [l]+a [r]≤w:配对成功,l++r--,分组数 + 1;
  4. a [l]+a [r]>w:最贵的单独分组,r--,分组数 + 1;
  5. 重复直到 l>r

逻辑证明(交换论证法)

交换论证法的核心是:假设存在最优解,通过交换其中的元素,证明最优解可以转化为贪心解,从而说明贪心解是最优的。

假设最优解中,存在一组配对方式与贪心策略不同:

  • 情况 1:**a [r](当前最贵)**单独分组。贪心解中 a [r] 单独分组,最优解中 a [r] 也必须单独分组(因为没有比 a [l] 更便宜的纪念品能和它配对),两者一致。
  • 情况 2:a [l]+a [r]≤w,但最优解中 a [l] 与 a [k](k<r)配对,a [r] 与 a [m](m>l)配对。此时交换 a [k] 和 a [r],得到 (a [l]+a [r]) 和 (a [k]+a [m]),两组总和都不超过 w,分组数不变,最优解转化为贪心解。

因此,贪心策略得到的分组数是最少的。

代码实现

cpp 复制代码
#include <iostream>
#include <algorithm>
using namespace std;

const int N = 3e4 + 10;
int w, n;
int a[N];

int main() {
    cin >> w >> n;
    for (int i = 1; i <= n; i++) cin >> a[i];
    sort(a + 1, a + 1 + n);
    
    int l = 1, r = n, ret = 0;
    while (l <= r) {
        if (a[l] + a[r] <= w) {
            l++;
            r--;
        } else {
            r--;
        }
        ret++;
    }
    
    cout << ret << endl;
    return 0;
}

优化点

  • 排序后用双指针遍历,时间复杂度O (nlogn)(主要消耗在排序),对于 n=3e4 完全适用;
  • 无需额外空间存储分组,直接通过指针移动计数,空间复杂度O (1)

例题 4:排座椅(洛谷 P1056)------ 贪心的 "优先级选择"

题目链接: https://www.luogu.com.cn/problem/P1056

题目描述

教室有 M 行 N 列座位,有 D 对同学会交头接耳(前后或左右相邻)。要设置 K 条横向通道和 L 条纵向通道,使交头接耳的同学对数最少。通道会隔开相邻的行或列,从而阻止这对同学交头接耳。

输入:第一行 M、N、K、L、D,后续 D 行是交头接耳的同学坐标(2≤M,N≤1e3,0≤K<M,0≤L<N,D≤2e3)

输出:第一行 K 个横向通道的位置,第二行 L 个纵向通道的位置(按升序排列)

示例输入:4 5 1 2 34 2 4 32 3 3 32 5 2 4

示例输出:22 4

题目分析

核心观察:横向通道只影响前后相邻的同学,纵向通道只影响左右相邻的同学。因此,横向和纵向通道的设置是独立的,可以分开处理。

对于横向通道:我们需要选择 K 个位置,使每个位置能隔开的交头接耳对数最多;纵向通道同理。这是一种 "选最大收益" 的贪心策略。

贪心策略

  1. 分别统计每个横向位置(第 i 行和第 i+1 行之间)能隔开的交头接耳对数;
  2. 分别统计每个纵向位置(第 j 列和第 j+1 列之间)能隔开的交头接耳对数;
  3. 对横向位置按 "收益"(隔开的对数)降序排序,选前 K 个;
  4. 对纵向位置按 "收益" 降序排序,选前 L 个;
  5. 将选中的位置按升序排列后输出。

逻辑证明

由于我们选择的是收益最大的 K 个横向位置和 L 个纵向位置,不存在其他选择能隔开更多的交头接耳对数。因此,这种 **"选最大收益"**的策略必然是最优的。

代码实现

cpp 复制代码
#include <iostream>
#include <algorithm>
using namespace std;

const int N = 1010;

struct Node {
    int index; // 通道位置(第index行/列和index+1之间)
    int cnt;   // 能隔开的交头接耳对数
} row[N], col[N];

// 按收益降序排序
bool cmp1(Node& x, Node& y) {
    return x.cnt > y.cnt;
}

// 按位置升序排序
bool cmp2(Node& x, Node& y) {
    return x.index < y.index;
}

int main() {
    int m, n, k, l, d;
    cin >> m >> n >> k >> l >> d;
    
    // 初始化:每个位置的index就是其本身
    for (int i = 1; i <= m; i++) row[i].index = i;
    for (int i = 1; i <= n; i++) col[i].index = i;
    
    while (d--) {
        int x1, y1, x2, y2;
        cin >> x1 >> y1 >> x2 >> y2;
        if (x1 == x2) { // 左右相邻,统计纵向通道
            int pos = min(y1, y2);
            col[pos].cnt++;
        } else { // 前后相邻,统计横向通道
            int pos = min(x1, x2);
            row[pos].cnt++;
        }
    }
    
    // 选择收益最大的K个横向通道和L个纵向通道
    sort(row + 1, row + 1 + m, cmp1);
    sort(col + 1, col + 1 + n, cmp1);
    
    // 按位置升序排列
    sort(row + 1, row + 1 + k, cmp2);
    sort(col + 1, col + 1 + l, cmp2);
    
    // 输出横向通道
    for (int i = 1; i <= k; i++) {
        cout << row[i].index << " ";
    }
    cout << endl;
    
    // 输出纵向通道
    for (int i = 1; i <= l; i++) {
        cout << col[i].index << " ";
    }
    cout << endl;
    
    return 0;
}

注意点

  • 通道位置是 "第 index 行 / 列和 index+1 之间",因此统计时要取 min (x1,x2)min (y1,y2)
  • 最终输出需要按位置升序排列,符合题目要求。

例题 5:矩阵消除游戏(牛客网)------ 贪心 + 枚举的 "组合拳"

题目链接: https://ac.nowcoder.com/acm/problem/200190

题目描述

n 行 m 列的矩阵,每个单元格有一个权值。进行 k 个回合,每个回合可选择一行或一列,将其所有单元格权值变为 0,并获得该行列的权值和。求最大得分。

输入:第一行 n、m、k,后续 n 行 m 列整数(1≤n,m≤15,1≤aᵢⱼ≤1e6,1≤k≤n*m)

输出:最大得分

示例输入:3 3 2101 1 1021 202 1100 8 100

示例输出:414(选择第一列和第三列,和为 101+1+100 + 102+1+100 = 414)

题目分析

这道题很容易陷入 "贪心陷阱":每次选择当前权值和最大的行或列。但这种策略是错误的 ------ 因为选择一行后,会影响后续列的权值和(该行的列元素会变为 0),反之亦然。

例如:

复制代码
100  9  10
  0  0  0
100  0  10

当k=2 时,贪心会选第一列(和 200)和第三列(和 20),总得分 220;但最优解是选第一行(和 119)和第三行(和 110),总得分 229。

因此,这道题需要 **"贪心 + 枚举"**的组合策略:先枚举所有可能的行选择,再对列进行贪心选择。

贪心策略

  1. 枚举所有行的选择情况(因为 n≤15,总共有 2¹⁵=32768 种情况,可行);
  2. 对于每种行选择(选 t 行):
    • 计算选中行的权值和;
    • 计算剩余列的权值和(未被选中的行的列元素和);
    • 从剩余列中选择 k-t 个权值和最大的列,累加得分;
  3. 所有情况中取最大得分。

逻辑证明

由于 n 和 m 很小,枚举所有行选择是可行的。对于每种行选择,列的选择必然是贪心选最大的 ------ 因为列之间是独立的(选择一列不会影响其他列的权值和),因此 "选最大的 k-t 列" 是最优的。

代码实现

cpp 复制代码
#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;

const int N = 20;
int n, m, k;
int a[N][N];
int col[N]; // 存储每列的权值和

// 统计x的二进制中1的个数(选中的行数)
int count_one(int x) {
    int ret = 0;
    while (x) {
        ret++;
        x -= x & -x; // 消除最低位的1
    }
    return ret;
}

// 按权值和降序排序
bool cmp(int a, int b) {
    return a > b;
}

int main() {
    cin >> n >> m >> k;
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < m; j++) {
            cin >> a[i][j];
        }
    }
    
    int max_score = 0;
    // 枚举所有行选择情况(st的二进制位表示是否选该行)
    for (int st = 0; st < (1 << n); st++) {
        int selected_rows = count_one(st);
        if (selected_rows > k) continue; // 选的行数超过k,跳过
        int remaining_cols = k - selected_rows; // 还能选的列数
        
        memset(col, 0, sizeof col);
        int score = 0;
        
        // 计算选中行的得分和剩余列的权值和
        for (int i = 0; i < n; i++) {
            if (st >> i & 1) { // 该行被选中
                for (int j = 0; j < m; j++) {
                    score += a[i][j];
                }
            } else { // 该行未被选中,累加列权值和
                for (int j = 0; j < m; j++) {
                    col[j] += a[i][j];
                }
            }
        }
        
        // 选择剩余列中权值和最大的remaining_cols个
        sort(col, col + m, cmp);
        for (int i = 0; i < remaining_cols; i++) {
            score += col[i];
        }
        
        max_score = max(max_score, score);
    }
    
    cout << max_score << endl;
    return 0;
}

优化点

  • 用二进制枚举行选择,能够高效遍历所有可能;
  • 列的权值和计算可以通过预处理优化,但由于 n 和 m 很小,直接计算也完全可行;
  • 时间复杂度 O (2ⁿ × m log m),对于 n=15、m=15,2¹⁵=32768,m log m≈50,总运算量约 1.6e6,效率很高。

三、简单贪心的常见策略总结

通过上面的例题,我们可以总结出简单贪心的几种常见策略模板,帮你快速应对同类问题:

1. 排序 + 选择类

  • 核心思路:先排序,再根据问题选择 "最小 / 最大"、"中位数" 等关键位置。
  • 适用场景:货仓选址(中位数)、纪念品分组(双指针配对)、最大子段和(排序后贪心选择,本题未用排序但属于选择类)。
  • 技巧:排序后常用双指针、遍历等方式进行贪心选择。

2. 收益最大化类

  • 核心思路:计算每个选择的 "收益",优先选择收益最大的。
  • 适用场景:排座椅(通道位置的收益是隔开的对数)、矩阵消除游戏(列的收益是权值和)。
  • 技巧:用数组统计收益,排序后选择前 k 个。

3. 舍弃负资产类

  • 核心思路:当当前累积的结果为负时,果断舍弃,重新开始。
  • 适用场景:最大子段和(sum<0 时重置)、股票买卖(LeetCode 121,当当前价格低于买入价时重新买入)。
  • 技巧:维护一个累积变量,实时更新最优结果,负累积时重置。

4. 枚举 + 贪心类

  • 核心思路:当直接贪心有陷阱时,枚举部分选择,再对剩余部分贪心。
  • 适用场景:矩阵消除游戏(枚举行选择,贪心选列)。
  • 技巧:枚举的维度要小(如 n≤15),否则会超时。

四、贪心算法的常见误区与避坑指南

1. 误区 1:认为 "贪心就是选最大 / 最小"

很多初学者会误以为贪心就是简单地选最大或最小,但实际上贪心策略是根据问题场景设计的。例如货仓选址选的是中位数,而不是最大或最小;最大子段和是舍弃负累积,而不是选最大的元素。

2. 误区 2:不证明策略正确性,直接编码

贪心算法的正确性不是直觉能保证的。例如矩阵消除游戏的 "选当前最大" 策略看似正确,实则有反例。因此,即使是简单贪心,也要尽量通过反证法、交换论证法等验证策略。

3. 误区 3:忽视边界情况

  • 全负序列的最大子段和(需初始化为极小值);
  • 纪念品分组中 n=1 的情况(必须单独分组);
  • 矩阵消除游戏中 k≥n+m 的情况(选所有行和列)。

4. 避坑指南

  • 遇到贪心问题,先尝试构造反例:如果能找到反例,说明策略错误;
  • 若无法构造反例,再尝试证明策略的正确性;
  • 编码时优先处理边界情况,再处理一般情况;
  • 对于数据量较大的问题(如 n≤1e5),优先选择 O (n) 或 O (n log n) 的贪心策略。

总结

贪心算法是一种 "当下最优" 的决策艺术,它不需要复杂的状态转移,却能高效解决很多问题。简单贪心作为入门基础,核心在于 "排序 + 选择"、"收益最大化"、"舍弃负资产" 等策略,而难点在于策略的设计和正确性证明。

学习贪心算法,不要急于求成,要通过大量例题积累经验,培养 "贪心直觉"。记住:贪心没有固定模板,但有通用思路 ------ 将问题拆分成子问题,每个子问题做出局部最优选择,并且证明这些选择能累积成全局最优。

当你能熟练解决简单贪心问题后,就可以进阶到更复杂的贪心问题(如哈夫曼编码、区间调度、推公式类贪心,这些我在后续的博客中会为大家详解),逐步构建完整的贪心算法知识体系。

最后,算法学习的核心是 "理解 + 实践"。希望这篇文章能帮你打开贪心算法的大门,多动手编码、多思考证明,你会发现贪心算法的魅力所在!

相关推荐
小欣加油3 小时前
leetcode 2536 子矩阵元素加1
数据结构·c++·算法·leetcode·矩阵
橘颂TA3 小时前
【剑斩OFFER】算法的暴力美学——二维前缀和
算法·c/c++·结构与算法
月半流苏3 小时前
Problem: lab-week10-exercise02 Building a Fiber Network
c++·算法·并查集
温宇飞3 小时前
计算机语言中的多态实现
c++
小龙报3 小时前
《VScode搭建教程(附安装包)--- 开启你的编程之旅》
c语言·c++·ide·vscode·单片机·物联网·编辑器
kyle~3 小时前
C++20--- concept 关键字 为模板参数提供了编译期可验证的约束机制
运维·c++
CS_浮鱼4 小时前
【C++进阶】异常
开发语言·c++
努力学算法的蒟蒻4 小时前
day14(11.14)——leetcode面试经典150
算法·leetcode
QT 小鲜肉4 小时前
【C++基础与提高】第十一章:面向对象编程进阶——继承与多态
java·linux·开发语言·c++·笔记·qt