习题与正则表达式

思路:

  1. 二分查找

    • left = 1(最小可能距离),right = L(最大可能距离)。

    • 每次取 mid = (left + right) / 2,判断是否可以通过增设 ≤ K 个路标使得所有相邻路标的距离 ≤ mid

  2. 贪心验证

    • 遍历所有相邻原始路标,计算它们之间的 gap

    • 对于每个 gap,计算需要插入的路标数 (gap - 1) / mid

    • 如果总增设数 required ≤ K,则 mid 可行,尝试更小的 mid;否则尝试更大的 mid

  3. 输出答案

    • 最终 ans 即为最小的"空旷指数"。
cpp 复制代码
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

int main() {
    int L, N, K;
    cin >> L >> N >> K;
    vector<int> markers(N);
    for (int i = 0; i < N; i++) {
        cin >> markers[i];
    }

    int left = 1;  // 最小可能距离
    int right = L;  // 最大可能距离
    int ans = L;

    // 二分查找最小的"空旷指数"
    while (left <= right) {
        int mid = (left + right) / 2;
        int required = 0;  // 需要增设的路标数量

        // 计算需要增设多少路标才能让所有间隔 ≤ mid
        for (int i = 1; i < N; i++) {
            int gap = markers[i] - markers[i - 1];
            required += (gap - 1) / mid;
        }

        if (required <= K) {
            ans = mid;
            right = mid - 1;  // 尝试更小的"空旷指数"
        } else {
            left = mid + 1;  // 需要更大的"空旷指数"
        }
    }

    cout << ans << endl;
    return 0;
}

思路:

  1. backtrack函数:这是递归回溯的核心函数。

    • n是目标美味程度,current是当前配料组合,sum是当前组合的总和,index是当前处理的配料索引。

    • 当处理完所有10个配料(index == 10),检查总和是否等于n,如果是,则保存当前组合。

    • 对于当前配料,尝试1、2、3克,递归处理下一个配料。通过剪枝条件提前终止无效的递归路径。

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

vector<vector<int>> solutions;  // 存储所有解决方案

void backtrack(int n, vector<int>& current, int sum, int index) {
    if (index == 10) {
        if (sum == n) {
            solutions.push_back(current);
        }
        return;
    }
    // 尝试1、2、3克
    for (int i = 1; i <= 3; ++i) {
        if (sum + i > n) continue;  // 剪枝:总和超过n,跳过
        // 剩下的配料即使全选1克也无法达到n,剪枝
        if (sum + i + (10 - index - 1) > n) continue;
        current[index] = i;
        backtrack(n, current, sum + i, index + 1);
    }
}

int main() {
    int n;
    cin >> n;
    vector<int> current(10);  // 当前组合
    backtrack(n, current, 0, 0);
    
    cout << solutions.size() << endl;
    for (const auto& sol : solutions) {
        for (int i = 0; i < 10; ++i) {
            cout << sol[i] << " ";
        }
        cout << endl;
    }
    return 0;
}

正则表达式

基本概念

  • 字符组 :用方括号 [] 表示,用于匹配方括号内的任意一个字符。例如,[abc] 可以匹配 abc 中的任意一个字符。
  • 量词 :用于指定前面的字符或字符组出现的次数。常见的量词有 *(零次或多次)、+(一次或多次)、?(零次或一次)、{n}(恰好 n 次)、{n,}(至少 n 次)、{n,m}nm 次)。例如,a* 表示匹配零个或多个 aa{2,4} 表示匹配 24a
  • 元字符 :具有特殊含义的字符,如 ^ 表示匹配字符串的开头,$ 表示匹配字符串的结尾,. 表示匹配除换行符以外的任意一个字符。例如,^a 表示以 a 开头的字符串,a$ 表示以 a 结尾的字符串。
  • 转义字符 :用反斜杠 \ 表示,用于转义元字符,使其失去特殊含义,而表示其本身。例如,\. 表示匹配字符 .\\ 表示匹配字符 \

常用操作

  • 匹配 :使用正则表达式来检查一个字符串是否符合特定的模式。例如,判断一个字符串是否是有效的电子邮件地址,可以使用正则表达式 ^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$
  • 查找 :在一个字符串中查找符合正则表达式模式的子串。例如,在一篇文章中查找所有的电话号码,可以使用正则表达式 \d{3}-\d{8}|\d{4}-\d{7}
  • 替换 :将匹配到的字符串替换为指定的内容。例如,将字符串中的所有数字替换为 *,可以使用正则表达式 \d 和替换字符串 *
  • 分割 :根据正则表达式的模式将字符串分割成多个子串。例如,将一个逗号分隔的字符串分割成数组,可以使用正则表达式 ,

示例

  • 匹配手机号码:^1[3-9]\d{9}$。这个正则表达式表示以 1 开头,第二位是 39 中的任意一个数字,后面跟着 9 个数字。
  • 匹配身份证号码:^\d{17}[\dXx]$。表示由 17 位数字和最后一位数字或 X(或 x)组成。

| 元字符 | 说明 |
|----------|--------------------------------------|-------------------|
| . | 匹配任意单个字符 (除换行符 \n) |
| ^ | 匹配字符串的开头 |
| $ | 匹配字符串的结尾 |
| * | 匹配前面的字符0次或多次 |
| + | 匹配前面的字符1次或多次 |
| ? | 匹配前面的字符0次或1次 |
| {n} | 匹配前面的字符恰好n次 |
| {n,} | 匹配前面的字符至少n次 |
| {n,m} | 匹配前面的字符n到m次 |
| [...] | 匹配括号内的任意一个字符(字符类) |
| [^...] | 匹配不在括号内的任意字符 |
| ` | ` | (匹配左边或右边的模式) |
| \d | 匹配数字 (等价于 [0-9]) |
| \D | 匹配非数字 (等价于 [^0-9]) |
| \w | 匹配字母、数字、下划线 (等价于 [a-zA-Z0-9_]) |
| \W | 匹配非字母、数字、下划线 |
| \s | 匹配空白字符(空格、制表符、换行符等) |
| \S | 匹配非空白字符 |
| \b | 匹配单词边界 |
| \B | 匹配非单词边界 |


3. 正则表达式示例

(1) 匹配数字

正则表达式 说明 匹配示例
\d+ 匹配1个或多个数字 123, 0, 456
\d{3} 匹配3位数字 123, 456
\d{2,4} 匹配2~4位数字 12, 123, 1234
相关推荐
小乐xiaole1 小时前
蓝桥杯 2025 C++组 省 B 题解
c++·蓝桥杯·深度优先
西贝爱学习1 小时前
数据结构:C语言版严蔚敏和解析介绍,附pdf
c语言·开发语言·数据结构
晓纪同学1 小时前
C++ Primer (第五版)-第十三章 拷贝控制
java·开发语言·c++
独家回忆3642 小时前
每日算法-250415
算法
m0_742950552 小时前
算法堆排序记录
数据结构·算法
arriettyandray2 小时前
Qt/C++学习系列之QTreeWidget的简单使用记录
c++·qt·学习
明月看潮生2 小时前
青少年编程与数学 02-016 Python数据结构与算法 15课题、字符串匹配
python·算法·青少年编程·编程与数学
zhaoyqcsdn3 小时前
C++对象池设计:从高频`new/delete`到性能飞跃的工业级解决方案
c++·经验分享·笔记
Spring_Lws3 小时前
aslist和list的区别
数据结构·list
CppPlayer-程序员阿杜3 小时前
poll为什么使用poll_list链表结构而不是数组 - 深入内核源码分析
网络·c++·链表·list·poll