算法设计与分析实验报告-贪心算法

 校课程的简单实验报告。

算法设计与分析实验报告-递归与分治策略

算法设计与分析实验报告-动态规划算法

算法设计与分析实验报告-贪心算法 

        dijkstra迪杰斯特拉算法(邻接表法)

算法设计与分析实验报告-回溯法

算法设计与分析实验报告-分支限界法 

算法设计与分析实验报告-分治法相关练题

北京大学出版社-算法设计与分析


一、实验目的

1.理解贪心算法的概念;

2.掌握贪心算法的基本要素;

3.掌握设计贪心算法的步骤和策略。

二、实验内容

使用贪心法求解以下问题,要求给出程序代码,并编译运行程序:

1.P118习题2。

2.P118习题5。

三、实验环境

1. 使用的操作系统及版本:

Windows 10

2. 使用的编译系统及版本:

CLion 2022.2.4

四、实验步骤及说明

1、P118习题2

对于用邻接链表表示的有向无环图,设计一个解单起点最短路径问题的线性算法。

dijkstra迪杰斯特拉算法(邻接表法)

代码如下:

//
// Created by GiperHsiue on 2022/11/27.
//
#include <iostream>
#include <vector>
#include <stack>
using namespace std;
#define INFINE 99999 // 定义最大
// 邻接表
struct ArcNode // 边信息
{
    int adjvex; //有向边的 目标顶点 下标(从1开始)
    int weight; //边的权值
    struct ArcNode *next; //邻接表, 指向下一个邻接边信息
};
struct VertexNode // 顶点
{
    int vertex; //顶点下标(1 ~)
    ArcNode *firstedge; // 有向边信息节点指针(源为vertex)
};
struct AdjList // 图
{
    vector<VertexNode> adjlist; //顶点数组
    int vexnum;  //顶点数 
    int arcnum;  //边数
};
// 图的初始化
void createGraph(AdjList& G){
    cout << "输入顶点数 边数: " << endl;
    cin >> G. vexnum >> G. arcnum;
    // 初始化G的顶点数组
    for(int i = 0; i <= G. vexnum; i ++){ // 下标从1开始, 所以初始化vexnum + 1个顶点(0无作用)
        VertexNode* tmp = new VertexNode;
        tmp->vertex = i, tmp->firstedge = nullptr;
        G. adjlist. emplace_back(*tmp);
    }
    //边信息
    // n1: 源顶点     n2: 目标顶点   we: 权重(距离)
    int n1, n2, we;
    cout << "输入边信息: (a b we): " << endl; // a -> b  weight: we
    for(int i = 0; i < G. arcnum; i ++){
        cin >> n1 >> n2 >> we;
        // 初始化一个边节点, 目标顶点为n2
        ArcNode* tmp = new ArcNode;
        tmp->adjvex = n2, tmp->weight = we;
        // 头插法 将边信息节点插入
        // 节约时间(尾插要一直遍历到尾部插入)
        tmp->next = G. adjlist[n1]. firstedge;
        G. adjlist[n1]. firstedge = tmp;
    }
}
// 获取两顶点之间权重weight(距离)
int getWeight(AdjList& G, int n1, int n2){
    if(n1 == n2) return 0;
    ArcNode* tmp = G. adjlist[n1]. firstedge;
    while(tmp){
        if(tmp->adjvex == n2) return tmp->weight;
        tmp = tmp->next;
    }
    // 两点之间没有边, 返回INFINE
    return INFINE;
}
void Dijkstra(AdjList& G, int ear, vector<int>& prev, vector<int>& dist){
    // 初始化
    // flag数组记录 某点是否纳入已找到点集合
    // prev数组记录 前驱顶点下标
    // dist数组记录 从源顶点ear 到 i顶点的最短路径
    vector<bool> flag (G. adjlist. size() + 1, false);
    for(int i = 1; i <= G. vexnum; i ++) dist[i] = getWeight(G, ear, i), prev[i] = ear;
    flag[ear] = true, prev[ear] = 0;
    // 开始
    for(int i = 2; i <= G. vexnum; i ++){
        int pos = 1; // 未纳入的距离最小的顶点
        int weiMin = INFINE;
        for(int j = 1; j <= G. vexnum; j ++){
            if(!flag[j] && dist[j] < weiMin){
                weiMin = dist[j], pos = j;
            }
        }
        flag[pos] = true;
        for(int j = 1; j <= G. vexnum; j ++){
            if(!flag[j]){ // 未纳入点集中, 找到pos到这些点的距离, 与dist数组比较是否更新
                int tmpWei = getWeight(G, pos, j);
                if(tmpWei != INFINE) tmpWei = tmpWei + weiMin; // 两点距离应该为ear -> pos -> j
                if(tmpWei < dist[j]) {
                    dist[j] = tmpWei; // 距离更小则更新dist
                    prev[j] = pos; // 前顶点更新为pos
                }
            }
        }
    }
}
// 找路径
void pathDist(vector<int>& prev, vector<int>& dist, int ear){
    // prev数组中为1有2种情况(djikstra初始化过程的时候全赋值为1, 后续一直未改变):
    // 1: 从ear到 顶点 只有 ear -> 顶点 这一条路最短
    // 2: 无法从ear到达的顶点
    for(int i = 1; i <= prev. size() - 1; i ++){
        stack<int> trace;
        if(ear == i) continue;
        cout << ear << " 到 " << i ;
        // 无连通
        if(dist[i] == INFINE) {
            cout << "无连通" << endl;
            continue;
        }
        cout << "最短距离: " << dist[i] << "  最短路径: ";
        int tmp = i;
        while(tmp){ //  源顶点prev是0
            trace. push(tmp);
            tmp = prev[tmp];
        }
        // 开始出栈, 栈顶一定是ear源顶点
        cout << trace. top();
        trace. pop();
        while(!trace. empty()){
            cout << " -> " << trace. top();
            trace. pop();
        }
        cout << endl;
    }
}
int main(){
    AdjList G;
    createGraph(G);
    // prev数组记录 前驱顶点下标
    vector<int> prev (G. vexnum + 1, 0);
    // dist数组记录 从源顶点ear 到 i顶点的最短路径
    vector<int> dist (G. vexnum + 1, INFINE);
    // 从源点ear 出发, 到达其余所有点的最短路径
    cout << "输入源顶点ear: ";
    int ear;
    cin >> ear;
    Dijkstra(G, ear, prev, dist);
    pathDist(prev, dist, ear);
    return 0;
}

测试如下:

  1. P118习题5 小船过河问题

一群人划船过河,河边只有一条船,这条船可以容纳两个人,船过河后需要一人将船开回,以便所有人都可以过河,每个人过河速度不一样,两个人过河速度取决于慢的那个人,请问最少需要多久让所有人过河?

//
// Created by GiperHsiue on 2022/11/27.
//
// 小船过河问题
#include <iostream>
#include <vector>
using namespace std;
// 归并排序
void mergeSort(vector<int>& num, int l, int r){
    if(l >= r) return;
    int mid = l + (r - l) / 2;
    mergeSort(num, l, mid), mergeSort(num, mid + 1, r);
    int a = l, b = mid + 1, k = 0;
    vector<int> tmp (r - l + 1, 0);
    while(a <= mid && b <= r){
        if(num[a] <= num[b]) tmp[k++] = num[a++];
        else tmp[k++] = num[b++];
    }
    while(a <= mid) tmp[k++] = num[a++];
    while (b <= r) tmp[k++] = num[b++];
    for(int i = 0, j = l; j <= r; i ++, j ++) num[j] = tmp[i];
}
int calTime(vector<int>& num){
    int cnt = num. size(), res = 0;
    while(cnt > 3){
        int tmp1 = num + 2 * num + num[cnt - 1];
        int tmp2 = 2 * num + num[cnt - 1] + num[cnt - 2];
        res += min(tmp1, tmp2);
        cnt -= 2;
    }
    if(cnt == 2) res += num;
    if(cnt == 3) res += num + num + num;
    return res;
}
int main(){
    int n;
    cin >> n;
    vector<int> people(n, 0);
    for(auto &x: people) cin >> x;
    mergeSort(people, 0, n - 1);
    cout << "过河最少时间: " << calTime(people) << endl;
    return 0;
}

代码如下:

测试如下:

五、实验小结及思考

通过本次实验对于贪心算法有了进一步的认识与理解,并运用贪心思维解决实际问题,理解贪心算法的概念,掌握贪心算法的基本要素,掌握设计贪心算法的步骤和策略。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

基于Java车间工时管理系统(源码+部署文档)

博主介绍&#xff1a; ✌至今服务客户已经1000、专注于Java技术领域、项目定制、技术答疑、开发工具、毕业项目实战 ✌ &#x1f345; 文末获取源码联系 &#x1f345; &#x1f447;&#x1f3fb; 精彩专栏 推荐订阅 &#x1f447;&#x1f3fb; 不然下次找不到 Java项目精品实…

web等保评测需要实机查看的操作系统、服务器、数据库和应用部分

“等保测评”全称是信息安全等级保护测评。是经公安部认证的具有资质的测评机构&#xff0c;依据国家信息安全等级保护规范规定&#xff0c;受有关单位委托&#xff0c;按照有关管理规范和技术标准&#xff0c;对信息系统安全等级保护状况进行检测评估的活动。 本文陆续将遇到的…

Python教程(18)——python文件操作详解

Python文件操作 Python文件操作基础操作使用with语句管理文件处理文件操作的异常处理文件路径 文本格式和二进制格式文本格式 (Text Mode)二进制格式 (Binary Mode)例子说明 文件操作的相关函数 所谓的文件操作是指对计算机中的文件进行读取、写入、修改和删除等操作。简单来说…

安装DataEase(Linux线上安装)修改端口

问题一&#xff1a;端口更改 警告本解决方法仅仅应急&#xff0c;如果找到了更好的方法请通知我&#xff0c;感谢你的理解&#xff01;&#xff01;&#xff01; 为了让mysql与dataease的端口不发生冲突&#xff0c;将 MySQL 外部运行端口参数 ${DE_MYSQL_PORT} 改为新端口&am…

一篇文章掌握 NestJS 所有的生命周期以及生命周期的执行时机

前言 NestJS 是一个用于构建高效、可扩展的 Node.js 服务器端应用程序的框架&#xff0c;它使用 TypeScript 作为开发语言&#xff0c;也支持原生的 JavaScript。在 NestJS 中&#xff0c;生命周期事件是一个重要的概念。在我们构建和管理应用程序时&#xff0c;有时需要在特定…

JUC常用并发工具类

JUC常用并发工具类 1、什么是JUC? JUC 就是 java.util.concurrent 包&#xff0c;这个包俗称 JUC&#xff0c;里面都是解决并发问题的一些东西&#xff0c;该包的位置位于 java 下 面的 rt.jar 包下面。 2、4大常用并发工具类 2.1 CountDownLatch CountDownLatch&#x…

[Angular] 笔记 17:提交表单 - ngSubmit

Submitting Forms (ngSubmit) 表单的一般完整写法&#xff1a; 如果表单验证失败&#xff0c;必须 disable 提交按钮&#xff0c;阻止用户提交不合法的数据。 提交表单后&#xff0c;与表单对应的 json 数据 post 到后端&#xff1a; {"id":1,"name":…

Windows上安装NodeJs

Windows上安装NodeJs 一、操作环境 操作系统: Windows 10 专业版 SDK:NodeJs v16.19.1&#xff08;安装鸿蒙IDE自动安装的NodeJs&#xff09; 二、安装过程 2.1下载Node.js安装包 官网下载地址&#xff1a; 下载历史版本安装也可 2.2 双击下载好的安装文件 2.3 打开下载…

从SLSA看软件供应链面临哪些威胁及对应解决方案

引言&#xff1a;软件制品供应链等级SLSA&#xff08;Supply-chain Levels for Software Artifacts&#xff09;是由由谷歌发起&#xff0c;基于行业共识建立的一个逐步完善供应链安全的规范。本文基于Google SLSA框架来看软件供应链安全面临的安全风险。 1. 简介 2023 年 4 月…

Educational cf 160的B题

Problem - B - Codeforces 找到最小操作次数&#xff0c;使得子串对应位与原来字符串对应位不相同。 交换是没有代价的&#xff0c;但是删除有代价。 首先复制两个一模一样的串&#xff0c;我们把下面作为固定串&#xff0c;然后对串中0和1的个数进行计数&#xff0c;由于我…

CEC2017(Python):五种算法(SSA、RFO、OOA、PSO、GWO)求解CEC2017

一、5种算法简介 1、麻雀搜索算法SSA 2、红狐优化算法RFO 3、鱼鹰优化算法OOA 4、粒子群优化算法PSO 5、灰狼优化算法GWO 二、CEC2017简介 参考文献&#xff1a; [1]Awad, N. H., Ali, M. Z., Liang, J. J., Qu, B. Y., & Suganthan, P. N. (2016). “Problem defin…

(001)Unit 编译 UTF8JSON

文章目录 编译 Dll编译报错附录 编译 Dll 新建工程&#xff1a; 注意 UnityEngineDll 的选择&#xff01;2022 版本的太高了&#xff01;&#xff01;&#xff01; 下载包&#xff0c;导入unity : 3. 将 unf8json 的源码拷贝到新建的工程。 4. 编译发布版本&#xff1a; 编译…

做抖店的话营业执照要办什么类型?法人必须是本人信息?问题解答

我是王路飞。 想在抖音开店的新手&#xff0c;好像对抖音个人店有一种迷之追求。 先劝告你们一句&#xff0c;贪小便宜容易吃大亏。 抖音个人店并不适合新手开通&#xff0c;它重在“试运营”这三个字&#xff0c;新手不仅无法正常把店铺做起来&#xff0c;而且后续还要把对…

MPLS动态协议LDP配置示例

一、预习&#xff1a; MPLS是一种根据报文中携带的标签来转发数据的技术&#xff0c;两台LSR必须在它们之间转的数据 的标签使用上“达成共识”。LSR之间可以运行LDP来告知其他LSR本设备上的标签绑定信息&#xff0c;从而实现标签报文的正确转发。 LSR&#xff1a;Label Switch…

在Java中输入连续三个数字并进行升序排序

思想 使用for循环对数组中的元素进行排序&#xff1a;需要创建数组&#xff0c;然后使用for循环进行比较&#xff0c;再者对排序后的元素进行输出。 代码 import java.io.*; import java.util.*; public class Sequence {public static void main(String[] args) throws IO…

javascript之location常用属性和方法

文章目录 前言为什么使用location的属性和方法呢&#xff1f;属性展示hrefhosthostnameportprotocolpathname 方法展示replace(url)assign(url)reload()toString() 总结属性总结&#xff1a;方法总结&#xff1a; 前言 本章学习的是location常用属性和方法 为什么使用location的…

C#多条件排序OrderBy、ThenBy

方法和效果 有多个排序条件&#xff0c;其实不用单独自己写排序方法的&#xff0c;C#内置了排序方法&#xff1a; 引用命名空间System.Linq 正向排序的方法&#xff1a;OrderBy首要条件&#xff1b;ThenBy次要条件&#xff0c;可以连续多个使用 同理&#xff0c;逆向排序对应…

探秘交互设计:深入了解五大核心维度!

交互式设计是用户体验&#xff08;UX&#xff09;设计的重要组成部分。本文将解释什么是交互设计&#xff0c;并分享一些有用的交互设计模型&#xff0c;并简要描述交互设计师通常做什么。 如何解释交互设计 交互式设计可以用一个简单的术语来理解&#xff1a;它是用户和产品…

新火种AI|AI正在让汽车成为“消费电子产品”

作者&#xff1a;一号 编辑&#xff1a;小迪 AI正在让汽车产品消费电子化 12月28日&#xff0c;铺垫许久的小米汽车首款产品——小米SU7正式在北京亮相。命里注定要造“电车”的雷军&#xff0c;在台上重磅发布了小米的五大自研核心技术。在车型设计、新能源技术以及智能科技…

Python中使用SQLite数据库的方法2-1

1 SQLite数据库简介 SQLite数据库是一种轻量级的、优秀的开源关系型数据库。它使用Python的标准库实现&#xff0c;并且存储数据库在普通文件中。这些文件在不同机器和操作系统之间是可以移植的&#xff0c;在很多安卓手机中&#xff0c;也是把SQLite作为嵌入数据库使用。 2 …