笔记:代码随想录算法训练营day67:Floyd 算法精讲、A * 算法精讲 (A star算法) 严重超时完结,不过,撒花

news2025/4/16 23:25:59

学习资料:代码随想录

Floyd 算法精讲

卡码网:97. 小明逛公园

首先明确floyd算法解决的是多源最短路径问题,对边的权的正负值没有要求,而且是动态规划的思想

五部曲:

定义:grid[i][j][k]表示从i出发到j经过[1...k]中某一个节点的最短距离

递推:1、节点i 到 节点j 的最短路径经过节点k,grid[i][j][k] = grid[i][k][k - 1] + grid[k][j][k - 1](i到k不经过k+k到j不经过k)

2、节点i 到 节点j 的最短路径不经过节点k,grid[i][j][k] = grid[i][j][k - 1]

取一个最小值:grid[i][j][k] = min(grid[i][k][k - 1] + grid[k][j][k - 1], grid[i][j][k - 1])

为什么最后一位是k-1呢,其实模拟一遍是最清楚的,个人浅显地认为,简要来说,还是动态规划中递推的思想:

假设你有节点 1~5,现在计算 grid[1][4][3]

  • 意思是:你正在计算 从 1 到 4 的最短路径,中间节点只能是 编号 ≤ 3 的点

所以这里你根本还不能用点 4 和点 5,它们 大于 k=3,不在当前阶段允许的中间节点集合内。

用点4和点5是递推到后面的事

初始化:i到j不经过节点的时候,即grid[i][j][0],可以通过输入就初始化了,其他值要给一个比10^4大的值,因为递推的过程是取小值;也不能太大,后面还要加,怕溢出。

遍历顺序:根据递推公式,得到grid[i][j][k]需要用到grid[i][k][k - 1],grid[k][j][k - 1] ,grid[i][j][k - 1],故吧k放在最外层

打印:略

//五部曲
//定义
//递推公式
//初始化
//遍历顺序
//打印
#include <iostream>
#include <vector>
using namespace std;
 
int main(){
    int n,m,u,v,w,q,start,end;
    cin>>n>>m;
    vector<vector<vector<int>>> roads(n+1,vector<vector<int>>(n+1,vector<int>(n+1,10005)));
    for(int i=0;i<m;i++){
        cin>>u>>v>>w;
        roads[u][v][0]=w;     //初始化
        roads[v][u][0]=w;
    }
 
    for(int k=1;k<=n;k++){
        for(int i=1;i<=n;i++){
            for(int j=1;j<=n;j++){
                roads[i][j][k]=min(roads[i][j][k-1],roads[i][k][k-1]+roads[k][j][k-1]);  //不经过k点和经过k点
            }
        }
    }
    cin>>q;
    while(q--){
        cin>>start>>end;
        if(roads[start][end][n]==10005) cout<<-1<<endl;
        else{
            cout<<roads[start][end][n]<<endl;
        }
    }
}

可以把空间复杂度压缩到O(n^2)

//五部曲
//定义
//递推公式
//初始化
//遍历顺序
//打印
#include <iostream>
#include <vector>
using namespace std;
 
int main(){
    int n,m,u,v,w,q,start,end;
    cin>>n>>m;
    vector<vector<int>> roads(n+1,vector<int>(n+1,10005));
    for(int i=0;i<m;i++){
        cin>>u>>v>>w;
        roads[u][v]=w;     //初始化
        roads[v][u]=w;
    }
 
    for(int k=1;k<=n;k++){
        for(int i=1;i<=n;i++){
            for(int j=1;j<=n;j++){
                roads[i][j]=min(roads[i][j],roads[i][k]+roads[k][j]);  //不经过k点和经过k点
            }
        }
    }
    cin>>q;
    while(q--){
        cin>>start>>end;
        if(roads[start][end]==10005) cout<<-1<<endl;
        else{
            cout<<roads[start][end]<<endl;
        }
    }
}

A * 算法精讲 (A star算法)

卡码网:126. 骑士的攻击

该说不说这道题的题目描述晃到我的,上来说马走日,象飞田,结果题目是求骑士的最少步数。

A*算法其实还是广度优先搜索,不过加上了启发式函数,启发式函数算的是从起点到终点并经过当前点要走的距离。

#include <iostream>
#include <queue>
#include <string.h>
using namespace std;
 
int moves[1001][1001];
int dir[8][2]={2,1,1,2,-1,2,-2,1,-2,-1,-1,-2,1,-2,2,-1};
int b1,b2;
  
struct knight{
    int x,y;             // 当前坐标
    int g,h,f;           // g=走过的代价,h=预估代价(启发式函数),f=g+h
    bool operator < (const knight& k) const{    //这是一个成员函数,重载了 < 运算符。
                                                //operator <:表示重载“小于”运算符
                                                //(const Knight &k):要和另一个 Knight 对象 k 进行比较
                                                //const:表示这个函数不会修改当前对象的成员变量
                                                //返回值是 bool,表示当前对象是否 小于 参数 k
 
        return k.f<f;      // 小顶堆,f 越小优先级越高
    }
};
 
priority_queue<knight> que;
int Heuristic(const knight& k){
    return (k.x-b1)*(k.x-b1)+(k.y-b2)*(k.y-b2);       //启发函数采用的是 欧几里得距离的平方(不开根号),因为这样避免了浮点计算,提高精度与效率
}
 
void astar(const knight& k){        //输入起点 k,然后开始扩展
    knight cur,next; 
    que.push(k);                    // 起点进队
    while(!que.empty()){
        cur = que.top(); que.pop(); //每次从堆里取出 f 最小的节点
        if(cur.x==b1&&cur.y==b2){   //终点判断
            break;
        }
        for(int i=0;i<8;i++){       //尝试扩展8个方向
            next.x = cur.x+dir[i][0];
            next.y = cur.y+dir[i][1];
            if(next.x<1||next.y>1000||next.y<1||next.y>1000){    //越界检查
                continue;
            }
            if(!moves[next.x][next.y]){                          //没访问过,更新状态并入队
                moves[next.x][next.y]=moves[cur.x][cur.y]+1;
                next.g=cur.g+5;                                  // 因为一步是 √5,不开根
                next.h=Heuristic(next);
                next.f=next.g+next.h;
                que.push(next);
            }
        }
    }
}
 
int main(){
    int n,a1,a2;
    cin>>n;
    while(n--){
        cin>>a1>>a2>>b1>>b2;
        memset(moves,0,sizeof(moves));
        knight start;
        start.x=a1;
        start.y=a2;
        start.g=0;
        start.h=Heuristic(start);
        start.f=start.g+start.h;
        astar(start);
        while(!que.empty()){                //多组输入,清空 moves 数组
            que.pop();
        }
        cout<<moves[b1][b2]<<endl;
    }
    return 0;
}

对于这个重载语法,作用是为了让 priority_queue 成为小顶堆 —— 也就是 f 越小,优先级越高priority_queue 默认是 大顶堆,它把“最大的”元素放在堆顶。所以你必须让“小的 f 看起来是“更大”的”,于是写成:return k.f < f;

priority_queue 会把 “operator < 为 true 的对象” 排在后面。

还可用lambda:

#include <iostream>
#include <queue>
#include <string.h>
using namespace std;
 
int moves[1001][1001];
int dir[8][2]={2,1,1,2,-1,2,-2,1,-2,-1,-1,-2,1,-2,2,-1};
int b1,b2;
  
struct knight{
    int x,y;             // 当前坐标
    int g,h,f;           // g=走过的代价,h=预估代价(启发式函数),f=g+h
    // bool operator < (const knight& k) const{    //这是一个成员函数,重载了 < 运算符。
    //                                             //operator <:表示重载“小于”运算符
    //                                             //(const Knight &k):要和另一个 Knight 对象 k 进行比较
    //                                             //const:表示这个函数不会修改当前对象的成员变量
    //                                             //返回值是 bool,表示当前对象是否 小于 参数 k
 
    //     return k.f<f;      // 小顶堆,f 越小优先级越高
    // }
};
 
//priority_queue<knight> que;
int Heuristic(const knight& k){
    return (k.x-b1)*(k.x-b1)+(k.y-b2)*(k.y-b2);       //启发函数采用的是 欧几里得距离的平方(不开根号),因为这样避免了浮点计算,提高精度与效率
}
 
void astar(const knight& k){        //输入起点 k,然后开始扩展
    auto cmp = [](const knight& a, const knight& b) {
        return a.f > b.f;  // f 小的优先
    };
    priority_queue<knight, vector<knight>, decltype(cmp)> que(cmp);
    knight cur,next; 
    que.push(k);                    // 起点进队
    while(!que.empty()){
        cur = que.top(); que.pop(); //每次从堆里取出 f 最小的节点
        if(cur.x==b1&&cur.y==b2){   //终点判断
            break;
        }
        for(int i=0;i<8;i++){       //尝试扩展8个方向
            next.x = cur.x+dir[i][0];
            next.y = cur.y+dir[i][1];
            if(next.x<1||next.y>1000||next.y<1||next.y>1000){    //越界检查
                continue;
            }
            if(!moves[next.x][next.y]){                          //没访问过,更新状态并入队
                moves[next.x][next.y]=moves[cur.x][cur.y]+1;
                next.g=cur.g+5;                                  // 因为一步是 √5,不开根
                next.h=Heuristic(next);
                next.f=next.g+next.h;
                que.push(next);
            }
        }
    }
}
 
int main(){
    int n,a1,a2;
    cin>>n;
    while(n--){
        cin>>a1>>a2>>b1>>b2;
        memset(moves,0,sizeof(moves));
        knight start;
        start.x=a1;
        start.y=a2;
        start.g=0;
        start.h=Heuristic(start);
        start.f=start.g+start.h;
        astar(start);
        // while(!que.empty()){                //多组输入,清空 moves 数组
        //     que.pop();
        // }
        cout<<moves[b1][b2]<<endl;
    }
    return 0;
}

A * 算法并不能保证一定是最短路,虽然本题求出来是最短路

memset函数:C 库函数 – memset() | 菜鸟教程

重载运算符:C++ 重载运算符和重载函数 | 菜鸟教程

lambda:C++ 函数 | 菜鸟教程

给陪伴我的网易云歌单也做个笔记:网易云音乐

音乐确实承载着太多回忆,可能将来的某一天,听到热河的前奏响起,闭上眼就会回到冬天坐在电脑前的那个晚上

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

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

相关文章

面试篇 - Transformer模型中的位置编码

1. 位置编码的引入 背景&#xff1a;Transformer模型通过自注意力机制&#xff08;Self-Attention&#xff09;处理序列数据&#xff0c;但自注意力机制本身并不包含序列中元素的位置信息。因此&#xff0c;需要一种方法来为模型提供位置信息。 解决方案&#xff1a;位置编码&…

vue+flask图书知识图谱推荐系统

文章结尾部分有CSDN官方提供的学长 联系方式名片 文章结尾部分有CSDN官方提供的学长 联系方式名片 关注B站&#xff0c;有好处&#xff01; 编号: F025 架构: vueflaskneo4jmysql 亮点&#xff1a;协同过滤推荐算法知识图谱可视化 支持爬取图书数据&#xff0c;数据超过万条&am…

vue2 走马灯 展示多个

使用 npm install “swiper”: “^11.2.4”, 在这里插入代码片 <template><section class"swiper pc-banner"><div class"swiper-container"><div class"swiper-wrapper"><div v-for"(item, index) in swiperD…

《MySQL从入门到精通》

文章目录 《MySQL从入门到精通》1. 基础-SQL通用语法及分类2. 基础-SQL-DDL-数据库操作3. 基础-SQL-DDL-表操作-创建&查询4. 基础-SQL-DDL-数据类型及案例4.1 数值类型4.2 字符串类型4.3 时间和日期类型 5. 基础-SQL-DDL-表操作-修改&删除5.1 DDL-表操作-修改5.2 DDL-表…

Linux: 线程同步

目录 一 前言 二 线程饥饿 三 线程同步 四 条件变量 1. cond &#xff08; condition&#xff09; 2. pthread_cond_wait() &#xff1a; 3. pthread_cond_signal() 五 条件变量的使用 一 前言 在上篇文章Linux : 多线程互斥-CSDN博客我们讲解了线程互斥的概念&#xff…

golang-context详解

Context是什么 cancel 其实就是通过chan select进行提前中断返回 如果没有context&#xff0c;携程之间怎么做这些交互呢&#xff1f;肯定也能做 跨线程通讯如共享内存&#xff0c;pipe等等都可以做到&#xff0c;但是就需要开发者对通讯设计建模、规划数据同步方式等&#xf…

Spring Boot 集成 RocketMQ 全流程指南:从依赖引入到消息收发

前言 在分布式系统中&#xff0c;消息中间件是解耦服务、实现异步通信的核心组件。RocketMQ 作为阿里巴巴开源的高性能分布式消息中间件&#xff0c;凭借其高吞吐、低延迟、高可靠等特性&#xff0c;成为企业级应用的首选。而 Spring Boot 通过其“约定优于配置”的设计理念&a…

AI与我共创WEB界面

记录一次压测后的自我技术提升 这事儿得从机房停电说起。那天吭哧吭哧做完并发压测,正准备截Zabbix监控图写报告,突然发现监控曲线神秘失踪——系统组小哥挠着头说:“上次停电后,zabbix服务好像就没起来过…” 我盯着空荡荡的图表界面,大脑的CPU温度可能比服务器还高。 其…

基于频率约束条件的最小惯量需求评估,包括频率变化率ROCOF约束和频率最低点约束matlab/simulink

基于频率约束条件的最小惯量评估&#xff0c;包括频率变化率ROCOF约束和频率最低点约束matlab/simulink 1建立了含新能源调频的频域仿真传函模型&#xff0c;虚拟惯量下垂控制 2基于构建的模型&#xff0c;考虑了不同调频系数&#xff0c;不同扰动情况下的系统最小惯量需求

深入理解浏览器的 Cookie:全面解析与实践指南

在现代 Web 开发中&#xff0c;Cookie 扮演着举足轻重的角色。它不仅用于管理用户会话、记录用户偏好&#xff0c;还在行为追踪、广告投放以及安全防护等诸多方面发挥着重要作用。随着互联网应用场景的不断丰富&#xff0c;Cookie 的使用和管理也日趋复杂&#xff0c;如何在保障…

Java 正则表达式综合实战:URL 匹配与源码解析

在 Web 应用开发中&#xff0c;我们经常需要对 URL 进行格式验证。今天我们结合 Java 的 Pattern 和 Matcher 类&#xff0c;深入理解正则表达式在实际应用中的强大功能&#xff0c;并剖析一段实际的 Java 示例源码。 package com.RegExpInfo;import java.util.regex.Matcher; …

【C++】前向声明(Forward Declaration)

前向声明&#xff08;Forward Declaration&#xff09;是在C、C等编程语言中&#xff0c;在使用一个类、结构体或其他类型之前&#xff0c;仅声明其名称而不给出完整定义的一种方式。 作用 减少编译依赖&#xff1a;当一个源文件包含大量头文件时&#xff0c;编译时间会显著增…

numpy.ma.masked_where:屏蔽满足条件的数组

1.函数功能 屏蔽满足条件的数组内容&#xff0c;返回值为掩码数组 2.语法结构 np.ma.masked_where(condition, a, copyTrue)3. 参数 参数含义condition屏蔽条件a要操作的数组copy布尔值&#xff0c;取值为True时&#xff0c;结果复制数组(原始数据不变)&#xff0c;否则返回…

【解决】bartender软件换网之后神秘变慢

下的山寨版本bartender软件&#xff0c;用着一直都挺好&#xff0c;结果一次换网之后&#xff0c;启动&#xff0c;排版&#xff0c;打印各种动作都要转个几分钟才行&#xff0c;非常奇怪。直接说解决过程。 首先联想网络没有动以及脱机的时候&#xff0c;都没有这个问题。那么…

[福游宝——AI智能旅游信息查询平台]全栈AI项目-阶段二:聊天咨询业务组件开发

简言 本项目旨在构建一个以AI智能体为核心的福建省旅游信息查询系统&#xff0c;聚焦景点推荐、路线规划、交通天气查询等功能&#xff0c;为游客提供智能化、便捷化的旅游信息服务。项目采用前后端分离架构&#xff0c;前端基于Vite TypeScript Vue3技术栈&#xff0c;搭配…

【教学类-102-11】蝴蝶外轮廓01——Python对黑白图片进行PS填充三种颜色+图案描边+图案填充白色+制作1图2图6图24图

背景需求: 用Python,对白色255背景的图片进行了透明化、制作点状或线段的描边裁剪线 【教学类-102-10】剪纸图案全套代码09——Python线条虚线优化版04(原图放大白背景)+制作1图2图6图24图-CSDN博客文章浏览阅读1k次,点赞27次,收藏8次。【教学类-102-10】剪纸图案全套代…

MCP的另一面

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗&#xff1f;订阅我们的简报&#xff0c;深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同&#xff0c;从行业内部的深度分析和实用指南中受益。不要错过这个机会&#xff0c;成为AI领…

微信小程序 - swiper轮播图

官方文档&#xff1a;https://developers.weixin.qq.com/miniprogram/dev/component/swiper.html <swiper indicator-color"ivory" indicator-active-color"#d43c33" indicator-dots autoplay><swiper-item><image src"/images/banner…

2025年第十六届蓝桥杯省赛C++ 研究生组真题

2025年第十六届蓝桥杯省赛C 研究生组真题 1.说明2.题目A&#xff1a;数位倍数&#xff08;5分&#xff09;3.题目B&#xff1a;IPv6&#xff08;5分&#xff09;4.题目C&#xff1a;变换数组&#xff08;10分&#xff09;5.题目D&#xff1a;最大数字&#xff08;10分&#xff…