C/C++蓝桥杯算法真题打卡(Day3)

news2025/3/10 20:00:48

一、P8598 [蓝桥杯 2013 省 AB] 错误票据 - 洛谷

算法代码:

#include<bits/stdc++.h>
using namespace std;

int main() {
    int N;
    cin >> N;  // 读取数据行数
    unordered_map<int, int> idCount;  // 用于统计每个ID出现的次数
    vector<int> ids;                  // 用于存储所有ID(方便排序)
    int num;

    // 读取所有ID
    for (int i = 0; i < N; i++) {
        while (cin >> num) {
            ids.push_back(num);  // 将ID存入vector
            idCount[num]++;      // 统计ID出现的次数
            if (cin.get() == '\n') break;  // 换行时结束当前行的读取
        }
    }

    // 对ID进行排序
    sort(ids.begin(), ids.end());

    int missing = -1, duplicate = -1;  // 断号ID和重号ID

    // 查找重号
    for (auto& pair : idCount) {
        if (pair.second == 2) {
            duplicate = pair.first;  // 找到重号
            break;
        }
    }

    // 查找断号
    for (int i = ids[0]; i <= ids.back(); i++) {
        if (idCount.find(i) == idCount.end()) {
            missing = i;  // 找到断号
            break;
        }
    }

    // 输出结果
    cout << missing << " " << duplicate << endl;

    return 0;
}

代码思路

1. 输入处理

  • 读取数据行数 N
  • 使用 unordered_map<int, int> 统计每个ID出现的次数。
  • 使用 vector<int> 存储所有ID,方便后续排序。

2. 读取所有ID

  • 使用 while (cin >> num) 逐行读取ID,直到遇到换行符 \n 结束当前行的读取。
  • 将每个ID存入 vector<int> ids 中,并在 unordered_map<int, int> idCount 中统计其出现次数。

3. 排序

  • 对 vector<int> ids 进行排序,方便后续查找断号和重号。

4. 查找重号

  • 遍历 unordered_map<int, int> idCount,找到出现次数为2的ID,即为重号。

5. 查找断号

  • 从最小ID(ids[0])到最大ID(ids.back())遍历,检查每个ID是否在 unordered_map<int, int> idCount 中。
  • 如果某个ID不在 unordered_map 中,则说明它是断号。

6. 输出结果

  • 输出断号ID missing 和重号ID duplicate

代码实现细节

1. 头文件

#include<bits/stdc++.h>
using namespace std;
  • 使用万能头文件 bits/stdc++.h,包含所有标准库。
  • 使用 using namespace std,避免每次调用标准库时需要写 std::

2. 主函数

int main() {
    int N;
    cin >> N;
  • 读取数据行数 N

3. 数据存储

unordered_map<int, int> idCount;
vector<int> ids;
int num;
  • unordered_map<int, int> idCount:用于统计每个ID出现的次数。
  • vector<int> ids:用于存储所有ID,方便后续排序。

4. 读取所有ID

for (int i = 0; i < N; i++) {
    while (cin >> num) {
        ids.push_back(num);
        idCount[num]++;
        if (cin.get() == '\n') break;
    }
}
  • 逐行读取ID,存入 vector<int> ids 中。
  • 使用 unordered_map<int, int> idCount 统计每个ID出现的次数。
  • 当遇到换行符 \n 时,结束当前行的读取。

5. 排序

sort(ids.begin(), ids.end());
  • 对 vector<int> ids 进行排序,方便后续查找断号和重号。

6. 查找重号

int missing = -1, duplicate = -1;
for (auto& pair : idCount) {
    if (pair.second == 2) {
        duplicate = pair.first;
        break;
    }
}
  • 遍历 unordered_map<int, int> idCount,找到出现次数为2的ID,即为重号。

7. 查找断号

for (int i = ids[0]; i <= ids.back(); i++) {
    if (idCount.find(i) == idCount.end()) {
        missing = i;
        break;
    }
}
  • 从最小ID(ids[0])到最大ID(ids.back())遍历,检查每个ID是否在 unordered_map<int, int> idCount 中。
  • 如果某个ID不在 unordered_map 中,则说明它是断号。

8. 输出结果

cout << missing << " " << duplicate << endl;
  • 输出断号ID missing 和重号ID duplicate

9. 返回

return 0;
  • 程序正常结束。

示例运行

输入

2
7 9
5 6 8 11 9

输出

10 9

总结

  • 代码通过 unordered_map 统计ID出现次数,结合排序和遍历,高效地找到断号和重号。
  • 时间复杂度为 O(n),其中 n 是ID的总数。
  • 代码逻辑清晰,适合处理题目描述中的场景。

还有另一种形式(不排序,直接使用哈希表):

#include <iostream>
#include <unordered_set>
using namespace std;

int main() {
    int N;
    cin >> N;  // 读取数据行数
    unordered_set<int> idSet;  // 用于存储所有ID
    int minID = INT_MAX, maxID = INT_MIN;  // 记录最小ID和最大ID
    int num;

    // 读取所有ID
    for (int i = 0; i < N; i++) {
        while (cin >> num) {
            idSet.insert(num);  // 将ID存入哈希表
            minID = min(minID, num);  // 更新最小ID
            maxID = max(maxID, num);  // 更新最大ID
            if (cin.get() == '\n') break;  // 换行时结束当前行的读取
        }
    }

    int missing = -1, duplicate = -1;  // 断号ID和重号ID

    // 查找重号
    unordered_set<int> seen;
    for (int id : idSet) {
        if (seen.count(id)) {
            duplicate = id;  // 找到重号
            break;
        }
        seen.insert(id);
    }

    // 查找断号
    for (int i = minID; i <= maxID; i++) {
        if (idSet.find(i) == idSet.end()) {
            missing = i;  // 找到断号
            break;
        }
    }

    // 输出结果
    cout << missing << " " << duplicate << endl;

    return 0;
}

二、P8775 [蓝桥杯 2022 省 A] 青蛙过河 - 洛谷 

算法代码: 

#include <bits/stdc++.h>
#define N 100005
using namespace std;

int n, T, h[N], ans;

int main() {
    // 读取河的宽度 n 和需要去学校的天数 T
    scanf("%d%d", &n, &T);
    // 将 T 乘以 2 得到实际过河的次数
    T <<= 1;
    
    // 读取每块石头的高度
    for (int i = 1; i < n; ++i) scanf("%d", &h[i]);
    
    // 使用滑动窗口的方法来找到满足条件的最小跳跃能力
    for (int i = 1, j = 0, sum = 0; i < n; i++) {
        // 扩展窗口的右边界,直到累加的高度大于等于 T
        while (j < n && sum < T) sum += h[++j];
        
        // 记录当前窗口的长度,即跳跃能力
        ans = max(ans, j - i + 1);
        
        // 缩小窗口的左边界,减去左边石头的高度
        sum -= h[i];
    }
    
    // 输出满足条件的最小跳跃能力
    printf("%d\n", ans);
    
    return 0;
}

规律:

        对于一个跳跃能力 y,青蛙能跳过河 2x 次,当且仅当对于每个长度为 y 的区间,这个区间内 h 的和都大于等于 2x

        这个问题涉及到对青蛙跳跃能力和石头高度分布的分析。我们需要理解为什么对于一个跳跃能力 y,青蛙能够跳过河 2x次,当且仅当对于每个长度为 y 的区间,这个区间内石头高度 h 的和都大于等于 2x。


1. 问题背景

  • 青蛙需要往返 2x 次,每次跳跃必须落在石头或岸上。

  • 每块石头的高度 h[i]表示这块石头可以被踩的次数。

  • 跳跃能力 y 表示青蛙一次跳跃的最大距离。


2. 跳跃能力 y 的含义

  • 如果青蛙的跳跃能力是 y,那么它每次跳跃的距离不能超过 y。

  • 这意味着青蛙在跳跃时,只能选择距离当前位置不超过 y 的石头。


3. 为什么需要每个长度为 y 的区间和 ≥2x

  • 必要性

    • 如果存在一个长度为 y的区间,其石头高度和 <2x,那么青蛙在这个区间内无法完成 2x 次跳跃。

    • 因为青蛙每次跳跃必须落在石头上,而石头的高度限制了可以被踩的次数。

    • 如果某个区间的石头高度和不足 2x,青蛙在这个区间内无法完成足够的跳跃次数。

  • 充分性

    • 如果每个长度为 y 的区间的石头高度和 ≥2x,那么青蛙可以在每个区间内完成足够的跳跃次数。

    • 因为青蛙的跳跃能力是 y,它可以在每个区间内自由选择石头进行跳跃,而不会受到石头高度不足的限制。


4. 具体分析

  • 青蛙的跳跃路径

    • 青蛙需要从起点跳到终点,再跳回起点,重复 x 次。

    • 每次跳跃的距离不能超过 y。

  • 区间的划分

    • 将河分成若干个长度为 y 的区间。

    • 每个区间内的石头高度和必须≥2x,因为青蛙需要在这些区间内完成 2x2x 次跳跃。

  • 石头高度的作用

    • 每块石头的高度 h[i] 表示这块石头可以被踩的次数。

    • 如果某个区间的石头高度和<2x,那么青蛙在这个区间内无法完成 2x 次跳跃。


5. 举例说明

假设:

  • 河的宽度 n=5。

  • 需要去学校的天数 x=1,实际过河次数 2x=2。

  • 石头高度 h=[3,1,2,1]。

跳跃能力 y=2

  • 区间划分:

    • 区间 1: 位置 1 和 2,高度和 3+1=4≥2。

    • 区间 2: 位置 2 和 3,高度和 1+2=3≥2。

    • 区间 3: 位置 3 和 4,高度和 2+1=3≥2。

  • 每个区间的石头高度和都 ≥2,因此青蛙可以完成 2 次跳跃。

跳跃能力 y=1

  • 区间划分:

    • 区间 1: 位置 1,高度和 3≥2。

    • 区间 2: 位置 2,高度和 1<2。

    • 区间 3: 位置 3,高度和 2≥2。

    • 区间 4: 位置 4,高度和 1<2。

  • 存在区间的石头高度和 <2,因此青蛙无法完成 2 次跳跃。


6. 总结

  • 对于一个跳跃能力 y,青蛙能够跳过河 2x 次,当且仅当对于每个长度为 y 的区间,这个区间内石头高度 h 的和都大于等于 2x。

  • 这是因为青蛙的跳跃能力限制了它每次跳跃的距离,而石头的高度限制了它可以在每块石头上踩的次数。

  • 如果某个区间的石头高度和不足2x,青蛙在这个区间内无法完成足够的跳跃次数。

  • 如果每个区间的石头高度和都 ≥2x,青蛙可以在每个区间内自由选择石头进行跳跃,完成 2x次跳跃。


代码思路:

这段代码的目的是通过滑动窗口的方法,找到小青蛙的最小跳跃能力 y,使得它能够完成 2x 次往返跳跃。以下是代码的详细思路:


1. 输入处理

  • 读取河的宽度 n 和需要去学校的天数 T

    • 使用 scanf("%d%d", &n, &T); 读取输入。

    • 河的宽度 n 表示从起点到终点共有 n 个位置(包括起点和终点)。

    • T 是小青蛙需要去学校的天数,实际过河次数是 2T(往返各一次)。

  • 将 T乘以 2

    • 使用 T <<= 1; 将 T左移一位,相当于 T=2T,表示实际过河次数。


2. 读取石头高度

  • 读取每块石头的高度

    • 使用 for (int i = 1; i < n; i++) scanf("%d", &h[i]); 读取每块石头的高度。

    • 数组 h 的下标从 1 开始,表示从起点到终点之间的 n−1块石头的高度。

    • h[i]表示距离起点 i的位置的石头高度。


3. 滑动窗口寻找最小跳跃能力

  • 初始化滑动窗口

    • 使用 for (int i = 1, j = 0, sum = 0; i < n; ++i) 初始化滑动窗口。

    • i是窗口的左边界,表示当前跳跃的起点。

    • j是窗口的右边界,表示当前跳跃的终点。

    • sum 是窗口内石头高度的累加和。

  • 扩展窗口的右边界

    • 使用 while (j < n && sum < T) sum += h[++j]; 扩展窗口的右边界。

    • 不断将右边界 j向右移动,累加石头的高度,直到累加的高度 sum大于等于 T。

    • 这一步的目的是找到一个窗口,使得窗口内的石头高度总和足够支持 2T 次跳跃。

  • 记录窗口的长度

    • 使用 ans = max(ans, j - i + 1); 记录当前窗口的长度。

    • 窗口的长度 j−i+1表示当前跳跃能力 y。

    • 通过取最大值,确保找到最小的跳跃能力。

  • 缩小窗口的左边界

    • 使用 sum -= h[i]; 缩小窗口的左边界。

    • 将左边界 i 向右移动,减去左边石头的高度,继续寻找更小的跳跃能力。


4. 输出结果

  • 输出满足条件的最小跳跃能力

    • 使用 printf("%d\n", ans); 输出结果。

    • ans 是满足条件的最小跳跃能力 yy。


代码的核心思想:

  • 滑动窗口

    • 通过滑动窗口的方法,动态调整窗口的左右边界,找到一个最小的窗口长度 y,使得窗口内的石头高度总和至少为 T。

    • 窗口的长度 y 表示小青蛙的跳跃能力。

  • 跳跃能力的定义

    • 跳跃能力 y 表示小青蛙一次跳跃的最大距离。

    • 通过滑动窗口找到的 y是最小的跳跃能力,使得小青蛙能够完成 2T 次跳跃。


代码的优化点:

  1. 滑动窗口的边界处理

    • 窗口的右边界 j 不能超过 n,否则会越界。

    • 窗口的左边界 i 逐步向右移动,确保窗口长度最小。

  2. 时间复杂度

    • 滑动窗口的时间复杂度是 O(n),因为每个石头最多被访问两次(一次扩展右边界,一次缩小左边界)。

    • 这种方法在 n≤10**5 的规模下非常高效。


总结:

这段代码通过滑动窗口的方法,高效地找到了小青蛙的最小跳跃能力 y,使得它能够完成 2T 次往返跳跃。滑动窗口的核心思想是动态调整窗口的左右边界,确保窗口内的石头高度总和满足条件,同时找到最小的窗口长度 y。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2311856.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

烟花燃放安全管控:智能分析网关V4烟火检测技术保障安全

一、方案背景 在中国诸多传统节日的缤纷画卷中&#xff0c;烟花盛放、烧纸祭祀承载着人们的深厚情感。一方面&#xff0c;烟花璀璨&#xff0c;是对节日欢庆氛围的热烈烘托&#xff0c;寄托着大家对美好生活的向往与期许&#xff1b;另一方面&#xff0c;袅袅青烟、点点烛光&a…

【Bert系列模型】

目录 一、BERT模型介绍 1.1 BERT简介 1.2 BERT的架构 1.2.1 Embedding模块 1.2.2 双向Transformer模块 1.2.3 预微调模块 1.3 BERT的预训练任务 1.3.1 Masked Language Model (MLM) 1.3.2 Next Sentence Prediction (NSP) 1.4 预训练与微调的关系 1.5 小结 二、BERT…

android接入rocketmq

一 前言 RocketMQ 作为一个功能强大的消息队列系统&#xff0c;不仅支持基本的消息发布与订阅&#xff0c;还提供了顺序消息、延时消息、事务消息等高级功能&#xff0c;适应了复杂的分布式系统需求。其高可用性架构、多副本机制、完善的运维管理工具&#xff0c;以及安全控制…

前端数据模拟 Mock.js 学习笔记

mock.js介绍 Mock.js是一款前端开发中拦截Ajax请求再生成随机数据响应的工具&#xff0c;可以用来模拟服务器响应 优点是&#xff1a;非常方便简单&#xff0c;无侵入性&#xff0c;基本覆盖常用的接口数据类型支持生成随机的文本、数字、布尔值、日期、邮箱、链接、图片、颜…

用DeepSeek-R1-Distill-data-110k蒸馏中文数据集 微调Qwen2.5-7B-Instruct!

下载模型与数据 模型下载&#xff1a; huggingface&#xff1a; Qwen/Qwen2.5-7B-Instruct HF MirrorWe’re on a journey to advance and democratize artificial intelligence through open source and open science.https://hf-mirror.com/Qwen/Qwen2.5-7B-Instruct 魔搭&a…

DeepSeek大模型 —— 全维度技术解析

DeepSeek大模型 —— 全维度技术解析 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;可以分享一下给大家。点击跳转到网站。 https://www.captainbed.cn/ccc 文章目录 DeepSeek大模型 —— 全维度技术解析一、模型架构全景解析1…

EasyRTC嵌入式音视频通话SDK:基于ICE与STUN/TURN的实时音视频通信解决方案

在当今数字化时代&#xff0c;实时音视频通信技术已成为人们生活和工作中不可或缺的一部分。无论是家庭中的远程看护、办公场景中的远程协作&#xff0c;还是工业领域的远程巡检和智能设备的互联互通&#xff0c;高效、稳定的通信技术都是实现这些功能的核心。 EasyRTC嵌入式音…

qt open3dAlpha重建

qt open3dAlpha重建 效果展示二、流程三、代码效果展示 二、流程 创建动作,链接到槽函数,并把动作放置菜单栏 参照前文 三、代码 1、槽函数实现 void on_actionAlpha_triggered();//alpha重建 void MainWindow::

《深入浅出数据索引》- 公司内部培训课程笔记

深入浅出数据索引 内容&#xff1a;索引理论&#xff0c;索引常见问题&#xff0c;索引最佳实践&#xff0c;sql优化实战&#xff0c;问答 哈希不支持范围查询 4层 几个亿 5层 几十亿上百亿 B树的分裂&#xff0c;50-50分裂 都是往上插一个元素&#xff08;红黑树是左右旋转&a…

PPT 技能:巧用 “节” 功能,让演示文稿更有序

在制作PPT时&#xff0c;你是否遇到过这样的情况&#xff1a;幻灯片越来越多&#xff0c;内容越来越杂&#xff0c;找某一页内容时翻得眼花缭乱&#xff1f;尤其是在处理大型PPT文件时&#xff0c;如果没有合理的结构&#xff0c;编辑和调整都会变得非常麻烦。这时候&#xff0…

Xss漏洞问题

https://bu1.github.io/2021/01/12/%E7%AC%AC%E5%8D%81%E4%BA%8C%E5%91%A8%EF%BC%9AXSS%E6%BC%8F%E6%B4%9E%E5%AD%A6%E4%B9%A0%E5%AE%9E%E6%88%98/ 后端绕开了前端&#xff0c;直接调用接口入库&#xff1a; <select οnchange“alert(1)”>12 前端拿到这个文本后&…

Docker概念与架构

文章目录 概念docker与虚拟机的差异docker的作用docker容器虚拟化 与 传统虚拟机比较 Docker 架构 概念 Docker 是一个开源的应用容器引擎。诞生于 2013 年初&#xff0c;基于 Go 语言实现。Docker 可以让开发者打包他们的应用以及依赖包到一个轻量级、可移植的容器中&#xf…

3.使用ElementUI搭建侧边栏及顶部栏

1. 安装ElementUI ElementUI是基于 Vue 2.0 的桌面端组件库。使用之前&#xff0c;需要在项目文件夹中安装ElementUI&#xff0c;在终端中输入以下命令&#xff0c;进行安装。 npm i element-ui -S并在main.js中引入ElementUI 2. 使用elmentUI组件进行页面布局 2.1 清空原…

C# OPC DA获取DCS数据(提前配置DCOM)

OPC DA配置操作手册 配置完成后&#xff0c;访问远程ip&#xff0c;就能获取到服务 C#使用Interop.OPCAutomation采集OPC DA数据&#xff0c;支持订阅&#xff08;数据变化&#xff09;、单个读取、单个写入、断线重连

不同开发语言之for循环的用法、区别总结

一、Objective-C &#xff08;1&#xff09;标准的c风格 for (int i 0; i < 5; i) {NSLog("i %d", i); } &#xff08;2&#xff09;for in循环。 NSArray *array ["apple", "banana", "orange"]; for (NSString *fruit in …

MuBlE:为机器人操作任务规划提供了逼真的视觉观察和精确的物理建模

2025-03-05&#xff0c;由华为诺亚方舟实验室、捷克技术大学和帝国理工学院联合开发的MuBlE&#xff08;MuJoCo and Blender simulation Environment&#xff09;模拟环境和基准测试。通过结合MuJoCo物理引擎和Blender高质量渲染&#xff0c;为机器人操作任务规划提供了逼真的视…

ASP.NET Core 6 MVC 文件上传

概述 应用程序中的文件上传是一项功能&#xff0c;用户可以使用该功能将用户本地系统或网络上的文件上传到 Web 应用程序。Web 应用程序将处理该文件&#xff0c;然后根据需要对文件进行一些验证&#xff0c;最后根据要求将该文件存储在系统中配置的用于保存文件的存储中&#…

2025年03月07日Github流行趋势

项目名称&#xff1a;ai-hedge-fund 项目地址url&#xff1a;https://github.com/virattt/ai-hedge-fund项目语言&#xff1a;Python历史star数&#xff1a;12788今日star数&#xff1a;975项目维护者&#xff1a;virattt, seungwonme, KittatamSaisaard, andorsk, arsaboo项目…

Cursor + IDEA 双开极速交互

相信很多开发者朋友应该和我一样吧&#xff0c;都是Cursor和IDEA双开的开发模式:在Cursor中快速编写和生成代码&#xff0c;然后在IDEA中进行调试和优化 在这个双开模式的开发过程中&#xff0c;我就遇到一个说大不大说小不小的问题&#xff1a; 得在两个编辑器之间来回切换查…

3.3.2 用仿真图实现点灯效果

文章目录 文章介绍Keil生成.hex代码Proteus仿真图中导入.hex代码文件开始仿真 文章介绍 点灯之前需要准备好仿真图keil代码 仿真图参考前文&#xff1a;3.3.2 Proteus第一个仿真图 keil安装参考前文&#xff1a;3.1.2 Keil4安装教程 keil新建第一个项目参考前文&#xff1a;3.1…