关于c++的几个简单算法

news2025/3/26 6:16:42

一. 动态规划(Dynamic Programming)

难点:状态转移方程的构建和初始化条件的设计
典型问题:01背包问题
分析
状态定义 dp[i][j] 表示前i个物品放入容量为j的背包的最大价值。状态转移需要判断是否选择当前物品。

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

int main() {
    int n, capacity;
    cin >> n >> capacity;
    int weight[n], value[n];
    int dp[n+1][capacity+1] = {0}; // 初始化为0

    for (int i = 0; i < n; i++) 
        cin >> weight[i] >> value[i];

    for (int i = 1; i <= n; i++) {
        for (int j = 0; j <= capacity; j++) {
            if (j >= weight[i-1])  // 能装下当前物品
                dp[i][j] = max(dp[i-1][j], dp[i-1][j - weight[i-1]] + value[i-1]);
            else 
                dp[i][j] = dp[i-1][j]; // 不装当前物品
        }
    }
    cout << dp[n][capacity];
    return 0;
}

关键点

  • 状态转移方程:max(不选当前物品,选当前物品)

  • 时间复杂度:O(n * capacity),需注意数据规模是否允许。

1. 矩阵取数游戏(P1005)

  • 题目类型:区间DP + 高精度

  • 难点:需要处理大数运算(__int128或高精度类),状态转移涉及从两端取数的最优解。

  • 状态定义dp[i][j] 表示区间 [i, j] 取数的最大得分。

  • 转移方程

    dp[i][j] = max(dp[i+1][j] * 2 + a[i], dp[i][j-1] * 2 + a[j]);
  • 代码参考:洛谷P1005题解。


2. 石子合并(P1880)

  • 题目类型:区间DP + 环形处理

  • 难点:环形问题需展开为链式(复制数组),并枚举分割点 k

  • 状态定义dp[i][j] 表示合并区间 [i, j] 的最小/最大代价。

  • 转移方程

dp[i][j] = min(dp[i][k] + dp[k+1][j] + sum[i][j]);
  • 代码参考:洛谷区间DP题单。


3. 过河卒(P1002)

  • 题目类型:坐标DP + 路径计数

  • 难点:处理马的控制点(不可达位置),初始化边界条件。

  • 状态定义dp[i][j] 表示到达 (i, j) 的路径数。

  • 转移方程

    dp[i][j] = dp[i-1][j] + dp[i][j-1]; // 非马控制点


4. 滑雪(P1434)

  • 题目类型:记忆化搜索(DFS + DP)

  • 难点:需递归遍历四个方向,记忆化存储已计算的结果。

  • 状态定义dp[x][y] 表示从 (x, y) 出发的最长滑坡长度。

  • 转移方程

    dp[x][y] = max(dfs(nx, ny) + 1); // (nx, ny) 为合法邻接点
  • 代码参考:动态规划与记忆化搜索题单。


5. 关路灯(P1220)

  • 题目类型:区间DP + 状态附加维度

  • 难点:需记录当前区间和位置(左/右端点),分类讨论移动方向。

  • 状态定义dp[i][j][0/1] 表示关闭 [i, j] 区间的灯后位于左/右端点的最小功耗。

  • 转移方程

    dp[i][j][0] = min(dp[i+1][j][0] + cost1, dp[i+1][j][1] + cost2);
  • 代码参考:洛谷区间DP题单。


6. 合唱队形(P3205)

  • 题目类型:区间DP + 双端插入

  • 难点:需记录最后插入的元素是左端还是右端。

  • 状态定义dp[i][j][0/1] 表示区间 [i, j] 以左/右端结尾的排列方案数。

  • 转移方程

    if (a[i] < a[i+1]) dp[i][j][0] += dp[i+1][j][0];
  • 代码参考:洛谷区间DP题单。

例题说明 :

  • 入门题:过河卒(P1002)、数字三角形(P1216)。

  • 进阶题:石子合并(P1880)、关路灯(P1220)。

  • 高难度题:矩阵取数(P1005)、滑雪(P1434)。


二. 图论 - 最短路径(Dijkstra算法)

难点:优先队列优化和松弛操作的理解
代码示例

#include <vector>
#include <queue>
using namespace std;

const int INF = 0x3f3f3f3f;
vector<pair<int, int>> graph[1001]; // 邻接表:graph[u] = {v, weight}
int dist[1001]; // 最短距离数组

void dijkstra(int start) {
    priority_queue<pair<int, int>, vector<pair<int, int>>, greater<>> pq;
    fill(dist, dist + 1001, INF);
    dist[start] = 0;
    pq.push({0, start});

    while (!pq.empty()) {
        int u = pq.top().second;
        int d = pq.top().first;
        pq.pop();
        if (d > dist[u]) continue; // 已找到更优路径,跳过

        for (auto &edge : graph[u]) {
            int v = edge.first, w = edge.second;
            if (dist[v] > dist[u] + w) { // 松弛操作
                dist[v] = dist[u] + w;
                pq.push({dist[v], v});
            }
        }
    }
}

关键点

  • 使用优先队列优化,每次取出距离最小的点。

  • 松弛操作:若通过当前点u到达v更近,则更新dist[v]

  • 注意:Dijkstra不能处理负权边!

1. P4779 【模板】单源最短路径(标准版)

  • 题目描述:给定有向图,求从源点出发到所有点的最短路径。

  • 算法:Dijkstra堆优化(优先队列实现)。

  • 关键点

    • 使用邻接表存图。

    • 优先队列优化,时间复杂度为O((V+E)logV)。

    • 注意不能在更新时判断vis,而应在出队时判断。

  • 代码参考:见洛谷P4779题解。


2. P3371 【模板】单源最短路径(弱化版)

  • 题目描述:与P4779类似,但数据范围较小,适合练习基础Dijkstra。

  • 算法:Dijkstra(未优化或优先队列优化)。

  • 关键点

    • 弱化版允许使用未优化的Dijkstra(O(V²))。

    • 输出要求中,不可达点输出2³¹-158。

  • 代码参考:见洛谷P3371题解。


3. P1339 Heat Wave G

  • 题目描述:无向图,求从起点到终点的最短路。

  • 算法:Dijkstra或SPFA(题目未禁用SPFA时)。

  • 关键点

    • 使用邻接矩阵存图(适合稠密图)。

    • 注意无向图的边需双向处理。

  • 代码参考:见洛谷P1339题解。


4. P1629 邮递员送信

  • 题目描述:求从源点到所有点的最短路及所有点返回源点的最短路之和。

  • 算法:Dijkstra + 反向建图。

  • 关键点

    • 正向图跑一次Dijkstra,反向图再跑一次。

    • 反向图可将“返回路径”转化为单源最短路问题。

  • 代码参考:见洛谷题单图论2-2。


5. P2296 寻找道路

  • 题目描述:在满足路径点出边均与终点连通的条件下,求最短路径。

  • 算法:拓扑排序 + Dijkstra/BFS。

  • 关键点

    • 先用反向图拓扑排序筛选合法点。

    • 再在合法点上跑最短路6。

  • 代码参考:见洛谷P2296题解。


6. P1144 最短路计数

  • 题目描述:求从起点到各点的最短路径条数(边权为1)。

  • 算法:BFS或Dijkstra(带DP统计)。

  • 关键点

    • dis[y] == dis[x]+1,则累加路径数。

    • 需模100003输出4。

  • 代码参考:见洛谷题单图论2-2。


题目编号名称算法难度
P4779单源最短路径(标准版)Dijkstra堆优化普及+/提高
P3371单源最短路径(弱化版)Dijkstra基础普及-
P1339Heat Wave GDijkstra/SPFA普及
P1629邮递员送信Dijkstra + 反向图普及+/提高
P2296寻找道路拓扑排序 + 最短路提高+/省选-
P1144最短路计数BFS/Dijkstra + DP普及+/提高

例题说明: 建议按顺序练习,从模板题(P3371、P4779)开始,逐步挑战综合应用题(如P2296)。更多题目可参考洛谷题单图论2-2。


三. 深度优先搜索(DFS)与剪枝

难点:剪枝条件的合理设计
典型问题:全排列问题
代码示例

#include <iostream>
using namespace std;

int n, path[10];
bool visited[10];

void dfs(int step) {
    if (step == n) { // 终止条件
        for (int i = 0; i < n; i++) 
            cout << path[i] << " ";
        cout << endl;
        return;
    }

    for (int i = 1; i <= n; i++) {
        if (!visited[i]) { // 剪枝:已用过的数字不再选
            visited[i] = true;
            path[step] = i;
            dfs(step + 1);
            visited[i] = false; // 回溯
        }
    }
}

int main() {
    cin >> n;
    dfs(0);
    return 0;
}

关键点

  • 使用visited数组避免重复选择,实现剪枝。

  • 回溯时恢复状态(visited[i] = false)。


四. 并查集(Union-Find)

难点:路径压缩和按秩合并的优化
代码示例

int parent[1001];
int rank[1001];

void init() {
    for (int i = 0; i < 1001; i++) {
        parent[i] = i;
        rank[i] = 1;
    }
}

int find(int x) { // 路径压缩
    if (parent[x] != x)
        parent[x] = find(parent[x]);
    return parent[x];
}

void union_set(int x, int y) { // 按秩合并
    int rootx = find(x), rooty = find(y);
    if (rootx == rooty) return;
    if (rank[rootx] > rank[rooty]) 
        parent[rooty] = rootx;
    else {
        parent[rootx] = rooty;
        if (rank[rootx] == rank[rooty]) 
            rank[rooty]++;
    }
}

关键点

  • find函数通过递归实现路径压缩,降低树高。

  • union_set根据秩的大小合并,避免树退化。


五. 贪心算法(Greedy)

难点:正确性证明和贪心策略的选择
典型问题:区间调度(选择最多不重叠区间)
代码示例

#include <vector>
#include <algorithm>
using namespace std;

struct Interval {
    int start, end;
};

bool compare(Interval &a, Interval &b) {
    return a.end < b.end; // 按结束时间排序
}

int maxIntervals(vector<Interval> intervals) {
    sort(intervals.begin(), intervals.end(), compare);
    int count = 0, last_end = -1;
    for (auto &itv : intervals) {
        if (itv.start >= last_end) {
            count++;
            last_end = itv.end;
        }
    }
    return count;
}

关键点

  • 贪心策略:优先选择结束时间早的区间。

  • 正确性证明:局部最优(选最早结束)导致全局最优。


总结

  1. 动态规划:从简单模型(如背包)入手,理解状态定义。

  2. 图论:熟练Dijkstra和Floyd算法的应用场景。

  3. 搜索:合理剪枝,避免暴力超时。

  4. 并查集:必须掌握路径压缩优化。

  5. 贪心:多练习经典问题,如区间问题、哈夫曼编码等。

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

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

相关文章

一套云HIS系统源码,系统融合HIS与EMR,基于云端部署,采用B/S架构与SaaS模式

云HIS系统完全基于云端部署&#xff0c;采用B/S架构&#xff0c;并通过软件即服务&#xff08;SaaS&#xff09;的形式面向二级及以下医院可快速交付、便捷运维、云化的医院核心业务平台产品。融合医院HIS和EMR两大主营系统&#xff0c;构建涵盖患者、费用、医嘱、电子病历等核…

C++数据结构(搜索二叉树)

1.二叉树搜索的概念 二叉搜索数也成为二叉排序树&#xff0c;它或者是一颗空树&#xff0c;或者是满足以下性质的树&#xff1a; 1.若他的左子树不为空&#xff0c;则左子树上的所有节点的值都小于等于根节点的值。 2.若他的右子树不为空&#xff0c;则右子树上的所有节点的值…

OpenCV图像拼接(6)图像拼接模块的用于创建权重图函数createWeightMap()

操作系统&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 编程语言&#xff1a;C11 算法描述 cv::detail::createWeightMap 是 OpenCV 库中用于图像拼接模块的一个函数&#xff0c;主要用于创建权重图。这个权重图在图像拼接过程中扮演着重…

炫酷的HTML5粒子动画特效实现详解

炫酷的HTML5粒子动画特效实现详解 这里写目录标题 炫酷的HTML5粒子动画特效实现详解项目介绍技术栈项目架构1. HTML结构2. 样式设计 核心实现1. 粒子类设计2. 动画效果实现星空效果烟花效果雨滴效果 3. 鼠标交互 性能优化效果展示总结 项目介绍 本文将详细介绍如何使用HTML5 C…

YoloV8训练和平精英人物检测模型

概述 和平精英人物检测&#xff0c;可以识别游戏中所有人物角色&#xff0c;并通过绘制框将人物选中&#xff0c;训练的模型仅仅具有识别功能&#xff0c;可以识别游戏中的视频、图片等文件&#xff0c;搭配Autox.js可以推理&#xff0c;实现实时绘制&#xff0c;但是对手机性…

BC93 公务员面试

&#x1f680;个人主页&#xff1a;BabyZZの秘密日记 &#x1f4d6;收入专栏&#xff1a;C语言练习题分享 &#x1f30d;文章目入 #include <stdio.h> int main() {int score 0, max 0, min 100, sum 0, count 0; while (scanf("%d", &score) ! EOF){…

3.0 Disruptor的使用介绍(一)

Disruptor: 其官网定义为&#xff1a;“A High Performance Inter-Thread Messaging Library”&#xff0c;即&#xff1a;线程间的高性能消息框架&#xff0c;与Labview的生产者、消费者模型很相似。 其组成部分比较多&#xff0c;先介绍几个常用的概念&#xff1a; …

[深度学习]图像分类项目-食物分类

图像分类项目-食物分类(监督学习和半监督学习) 文章目录 图像分类项目-食物分类(监督学习和半监督学习)项目介绍数据处理设定随机种子读取文件内容图像增广定义Dataset类 模型定义迁移学习 定义超参Adam和AdamW 训练过程半监督学习定义Dataset类模型定义定义超参训练过程 项目介…

java8循环解压zip文件---实现Excel文件数据追加

java8循环追加Excel数据 实际遇到问题&#xff1a;定期获取zip文件&#xff0c;zip文件内有几个固定模板的Excel文件&#xff0c;有的Excel文件可能还包含多个sheet。 有段时间一次性获取到好几个zip包&#xff0c;需要将这些包都解压&#xff0c;并且按照不同的文件名、sheet进…

基于SpringBoot的电影售票系统

作者&#xff1a;计算机学姐 开发技术&#xff1a;SpringBoot、SSM、Vue、MySQL、JSP、ElementUI、Python、小程序等&#xff0c;“文末源码”。 专栏推荐&#xff1a;前后端分离项目源码、SpringBoot项目源码、Vue项目源码、SSM项目源码、微信小程序源码 精品专栏&#xff1a;…

SQL Server 2022 安装问题

一、安装与配置问题 1. SQL Server 2022 安装失败怎么办&#xff1f; 常见原因&#xff1a; 硬件或操作系统不满足最低要求&#xff08;如内存、磁盘空间不足&#xff09;。未关闭防火墙或杀毒软件。之前版本的 SQL Server 残留文件未清理。 解决方案&#xff1a; 确保硬件配…

MySQL 8.0.41安装教程(附安装包)mysql8.0.41图文详细安装教程

文章目录 前言一、MySQL 8.0.41下载安装包二、MySQL 8.0.41安装教程1.启动安装程序2.选择安装模式3.选定安装组件4.确认安装设置5.执行安装操作6.安装进行中7.设置数据库密码8.继续点击下一步9.执行配置操作10.完成配置11. 再次点击下一步12.结束安装向导 三、MySQL 8.0.41配置…

深入解析 C++20 中的 std::bind_front:高效函数绑定与参数前置

文章目录 1. 什么是 std::bind_front&#xff1f;2. 使用 std::bind_front2.1 基本用法2.2 绑定多个参数 3. 优势与特点3.1 简化代码3.2 支持可调用对象3.3 支持完美转发 4. 实际应用场景4.1 事件处理4.2 算法通用化4.3 成员函数调用 5. 总结 在现代 C 编程中&#xff0c;函数绑…

python裁剪nc文件数据

问题描述&#xff1a; 若干个nc文件储存全球的1850-2014年月尺度的mrro数据(或其他数据)&#xff0c;从1850-1到2014-12一共1980个月&#xff0c;要提取出最后35年1980.1~2014.12年也就是420个月的数据。 代码实现 def aaa(input_file,output_file,bianliang,start_index,en…

CSS网格布局Grid

目录 一、Grid 网格布局 1.Grid 布局基础 2.网格容器属性 3.网格项目属性 4.高级功能 5.典型应用场景 6.最佳实践 二、Flex和Grid对比 示例&#xff1a; 一、Grid 网格布局 CSS Grid 是一种强大的二维布局系统&#xff0c;能够以行和列的方式精确控制网页布局。它比传…

医院挂号预约小程序|基于微信小程序的医院挂号预约系统设计与实现(源码+数据库+文档)

医院挂号预约小程序 目录 基于微信小程序的医院挂号预约系统设计与实现 一、前言 二、系统功能设计 三、系统实现 1、小程序用户端 2、系统服务端 &#xff08;1&#xff09; 用户管理 &#xff08;2&#xff09;医院管理 &#xff08;3&#xff09;医生管理 &#xf…

蓝桥杯第十届 特别的数

题目描述 小明对数位中含有 2、0、1、9 的数字很感兴趣&#xff08;不包括前导 0&#xff09;&#xff0c;在 1 到 40 中这样的数包括 1、2、9、10 至 32、39 和 40&#xff0c;共 28 个&#xff0c;他们的和是 574。 请问&#xff0c;在 1 到 n 中&#xff0c;所有这样的数的…

Qt开发:QInputDialog的使用

文章目录 一、QInputDialog的介绍二、 QInputDialog的基本用法三、使用 QInputDialog的实例四、QInputDialog的信号与槽 一、QInputDialog的介绍 QInputDialog 是 Qt 提供的一个对话框类&#xff0c;用于获取用户输入的文本、整数或浮点数。它提供了简单易用的静态方法和可定制…

redis--JavaSpring客户端

目录 一、引言 二、配置 三、相关操作 四、总结 一、引言 本篇文章会将redis与spring项目进行结合&#xff0c;看看再spring项目中&#xff0c;redis是如何使用的 二、配置 三、相关操作 四、总结 在spring项目中的使用和在基础项目上的使用有差异&#xff0c;但是差异并不大…