当前位置: 首页 > news >正文

算法日记 49 day 图论(A*算法)

这算是算法的最后一篇了,原本A*之前还有一些相关的最短路径算法的,比如dijkstra的堆优化,SPFA等等,但是有些我没看懂,就不写了,用A*做个结尾。

题目:骑士的攻击

127. 骑士的攻击 (kamacoder.com)

题目描述

在象棋中,马和象的移动规则分别是“马走日”和“象走田”。现给定骑士的起始坐标和目标坐标,要求根据骑士的移动规则,计算从起点到达目标点所需的最短步数。

棋盘大小 1000 x 1000(棋盘的 x 和 y 坐标均在 [1, 1000] 区间内,包含边界)

输入描述

第一行包含一个整数 n,表示测试用例的数量,1 <= n <= 100。

接下来的 n 行,每行包含四个整数 a1, a2, b1, b2,分别表示骑士的起始位置 (a1, a2) 和目标位置 (b1, b2)。

输出描述

输出共 n 行,每行输出一个整数,表示骑士从起点到目标点的最短路径长度。

输入示例

6
5 2 5 4
1 1 2 2
1 1 8 8
1 1 8 7
2 1 3 3
4 6 4 6

输出示例

2
4
6
5
1
0

提示信息

骑士移动规则如图,红色是起始位置,黄色是骑士可以走的地方。

 

题目分析:

        在一个平面内,从一点到另外一点,很明显的广搜类题目。我们先来看看广搜怎么写

#include<iostream>
#include<queue>
#include<string.h>
using namespace std;
int moves[1001][1001];
int dir[8][2]={-2,-1,-2,1,-1,2,1,2,2,1,2,-1,1,-2,-1,-2};void bfs(int a1,int a2,int b1,int b2){queue<int> que;que.push(a1);que.push(a2);while(!que.empty()){int m=que.front();que.pop();int n=que.front();que.pop();if(m == b1 && n == b2)break;for(int i=0;i<8;i++){int mm=m+dir[i][0];int nn=n+dir[i][1];if(mm < 1 || mm > 1000 || nn < 1 || nn > 1000)continue;if(!moves[mm][nn]){moves[mm][nn]=moves[m][n]+1;que.push(mm);que.push(nn);}}}
}int main(){int n;int a1,a2,b1,b2;cin>>n;while(n--){cin>>a1>>a2>>b1>>b2;memset(moves,0,sizeof(moves));//分配空间,填入0bfs(a1,a2,b1,b2);cout << moves[b1][b2] << endl;}return 0;
}

虽然能解出来,但是由于棋盘太大了,会超时。

我们来看看A*的思路

A*实际上就是一直启发式的遍历,它也可以通过dijkstra和广搜写出来,主要区别在于给我们的图是什么样的,像无权图,广搜就可以了,如果带权值,那么使用dijkstra会简便一些。

那么A*的启发性是什么意思呢?

这个是常规广搜的遍历过程,他会一圈一圈的去搜索

这是A*的遍历过程,可以看到他的遍历是带有方向性的。

那么这个启发性是怎么来的呢?在广搜中我们获取需要遍历的结点是这样的,从队列中取出队首元素

        int m=que.front();que.pop();int n=que.front();que.pop();

而这个取出的结点就是我们需要控制的,我们给队列中的元素给一个权值并且排序。

每个节点的权值为F,给出公式为:F = G + H

G:起点达到目前遍历节点的距离

H:目前遍历的节点到达终点的距离

起点达到目前遍历节点的距离 + 目前遍历的节点到达终点的距离 就是起点到达终点的距离。

本题的图是无权网格状,在计算两点距离通常有如下三种计算方式:

  1. 曼哈顿距离,计算方式: d = abs(x1-x2)+abs(y1-y2)
  2. 欧氏距离(欧拉距离) ,计算方式:d = sqrt( (x1-x2)^2 + (y1-y2)^2 )
  3. 切比雪夫距离,计算方式:d = max(abs(x1 - x2), abs(y1 - y2))

x1, x2 为起点坐标,y1, y2 为终点坐标 ,abs 为求绝对值,sqrt 为求开根号,

选择哪一种距离计算方式 也会导致 A * 算法的结果不同。

本题,采用欧拉距离才能最大程度体现 点与点之间的距离。

所以 使用欧拉距离计算 和 广搜搜出来的最短路的节点数是一样的。 (路径可能不同,但路径上的节点数是相同的)

那么我们在求出权值之和,根据权值确定我们需要取出的结点然后再去遍历即可。

看看代码实现

#include<iostream>
#include<queue>
#include<string.h>
using namespace std;
int moves[1001][1001];
int dir[8][2]={-2,-1,-2,1,-1,2,1,2,2,1,2,-1,1,-2,-1,-2};
int b1, b2;
// F = G + H
// G = 从起点到该节点路径消耗
// H = 该节点到终点的预估消耗struct Knight{ //记录位置以及权值信息int x,y;int g,h,f;bool operator < (const Knight & k) const{  // 重载运算符, 从小到大排序return k.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)
{Knight cur, next; que.push(k);while(!que.empty()){cur=que.top(); que.pop();if(cur.x == b1 && cur.y == b2)break;for(int i = 0; i < 8; i++){next.x = cur.x + dir[i][0];next.y = cur.y + dir[i][1];if(next.x < 1 || next.x > 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;// 开始计算Fnext.g = cur.g + 5; // 统一不开根号,这样可以提高精度,马走日,1 * 1 + 2 * 2 = 5next.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()) que.pop(); // 队列清空cout << moves[b1][b2] << endl;}return 0;
}

需要注意的是

A * 算法并不能保证一定是最短路,因为在设计 启发式函数的时候,要考虑 时间效率与准确度之间的一个权衡。

另外,给出 多个可能的目标,然后在这多个目标中 选择最近的目标,这种 A * 就不擅长了, A * 只擅长给出明确的目标 然后找到最短路径。

对于更详细的解析与其他语言的代码块,可以去代码随想录上查看。

代码随想录 (programmercarl.com)

已刷题目:145

那么算法日记就完结啦。近150题,各种类型都有,接下来就是二刷啦。

相关文章:

算法日记 49 day 图论(A*算法)

这算是算法的最后一篇了&#xff0c;原本A*之前还有一些相关的最短路径算法的&#xff0c;比如dijkstra的堆优化&#xff0c;SPFA等等&#xff0c;但是有些我没看懂&#xff0c;就不写了&#xff0c;用A*做个结尾。 题目&#xff1a;骑士的攻击 127. 骑士的攻击 (kamacoder.co…...

服务器批量清理redis keys,无法适用客户端必须直连的情况

在 Redis 中&#xff0c;批量清理指定模式的键&#xff08;例如 memberCardData:*&#xff09;可以通过多种方法来实现。需要注意的是&#xff0c;Redis 的命令执行是单线程的&#xff0c;因此对大量键进行操作时可能会阻塞服务器。以下是几种常见的方法&#xff1a; shell K…...

Grafana配置告警规则推送企微机器人服务器资源告警

前提 已经部署Grafana&#xff0c;并且dashboard接入数据 大屏编号地址&#xff1a;Node Exporter Full | Grafana Labs 创建企微机器人 备注&#xff1a;群里若有第三方外部人员不能创建 机器人创建完成&#xff0c;记录下来Webhook地址 Grafana配置告警消息模板 {{ define &…...

数字货币金融研究,深度学习虚拟币价格预测 数据集 市值top20 (2014年—2024年)

比特币&#xff0c;以太坊&#xff0c;狗狗币&#xff0c;屎币&#xff0c;模因币 声明 此数据集的目的是 用于数字货币金融研究&#xff0c;深度学习虚拟币价格预测 1、数据集 2014年——2024年 市值top20 比特币&#xff0c;以太坊&#xff0c;屎币&#xff0c;狗狗币交易…...

druid.properties图标是齿轮

一、问题 在IDEA中&#xff0c; druid.properties图标是齿轮 二、原因 2023版本开始&#xff0c;IDEA新的UI的问题 三、解决方法 1、点击右上角的齿轮图标 2、点击Settings 3、Appearance & Behavior---->New UI---->取消勾选“Enable new UI”---->右下角OK 4…...

【图像处理】利用numpy、opencv、python实现车牌检测

| 利用opencv实现车牌检测 整体流程涉及5个部分 图像通道转换对比度增强边缘连接二值化边界区域裁剪 图像通道转换 将RGB图像转换为HSV图像&#xff0c;仅保留V通道。V通道表示颜色的明暗&#xff0c;常用于图像对比度拉伸、直方图均衡化等流程。 原图像&#xff1a; V通…...

ModuleNotFoundError: No module named ‘torchvision.transforms.functional_tensor‘

问题&#xff1a; 运行代码时&#xff0c;报错&#xff1a; … File “/home/xzy/anaconda3/envs/groundinggpt/lib/python3.10/site-packages/pytorchvideo/transforms/augmix.py”, line 6, in from pytorchvideo.transforms.augmentations import ( File “/home/xzy/anac…...

Android无障碍服务监听实现自动点击按钮

原理&#xff1a; 通过监听窗口改变事件&#xff0c;监听目标应用&#xff0c;通过视图ID&#xff08;或文本、或描述、或其他如坐标之类的&#xff09;找到目标视图&#xff0c;使用无障碍动作点击方法点击它 无障碍服务实现&#xff1a; 1、写一个自己的无障碍服务继承Acc…...

Deveco Studio首次编译项目初始化失败

编译项目失败 Ohpm install失败的时候重新使用管理者打开程序 build init 初始化失败遇到了以下报错信息 Installing pnpm8.13.1... npm ERR! code CERT_HAS_EXPIRED npm ERR! errno CERT_HAS_EXPIRED npm ERR! request to https://registry.npm.taobao.org/pnpm failed, r…...

Redis缓存应用场景【Redis场景上篇】

文章目录 1.缓存基础2.缓存异步场景1.缓存穿透2.缓存击穿3.缓存雪崩总结 3.缓存一致性 1.缓存基础 Redis由于性能高效&#xff0c;通常可以做数据库存储的缓存。一般而言&#xff0c;缓存分为服务端缓存和客户端缓存。缓存有以下三种模式&#xff1a; Cache Aside&#xff08…...

线程与进程基础

文章目录 前言一、 线程与进程1.1 什么是线程与进程&#xff1f;1.2 并发与并行1.3 同步调用与异步调用1.4 为什么要使用多线程&#xff1f; 前言 在学习juc前&#xff0c;需要先对进程和线程之间整体有一个认知。我们之前或多或少接触过&#xff0c;一些特别高大上的概念&…...

electron 打包 webview 嵌入需要调用电脑摄像头拍摄失败问题

electron 打包 webview 嵌入需要调用电脑摄像头拍摄失败问题 这篇文章是接我cocos专栏的上一篇文章继续写的&#xff0c;我上一篇文章写的是 cocos 开发触摸屏项目&#xff0c;需要嵌入一个网页用来展示&#xff0c;最后通过 electron 打包成 exe 程序&#xff0c;而且网页里面…...

OpenCV的简单练习

1、读取一张彩色图像并将其转换为灰度图。 import matplotlib.pyplot as pltimg plt.imread("./flower.png") # 灰度化 img_gray img[:,:,0]*0.299 img[:,:,1]*0.587 img[:,:,2]*0.114plt.subplot(121) plt.imshow(img) plt.subplot(122) plt.imshow(img_gray,c…...

JAVA:建造者模式(Builder Pattern)的技术指南

1、简述 建造者模式(Builder Pattern)是一种创建型设计模式,它通过将对象的构造过程与表示分离,使得相同的构造过程可以创建不同的表示。建造者模式尤其适用于创建复杂对象的场景。 设计模式样例:https://gitee.com/lhdxhl/design-pattern-example.git 本文将详细介绍建…...

12.11函数 结构体 多文件编译

1.脑图 定义一个数组&#xff0c;用来存放从终端输入的5个学生的信息【学生的信息包含学生的姓名、年纪、性别、成绩】 1>封装函数 录入5个学生信息 2>封装函数 显示学生信息 3>封装函数 删除第几个学生信息&#xff0c;删除后调用显示学生信息函数 显示 4> 封…...

Debezium系列之:使用Debezium采集oceanbase数据库

Debezium系列之:使用Debezium采集oceanbase数据库 一、oceanbase数据库二、安装OceanBase三、安装oblogproxy四、基于Docker的简单采集案例五、生产实际应用案例Debezium 是一个开源的分布式平台,用于监控数据库变化和捕捉数据变动事件,并以事件流的形式导出到各种消费者。D…...

VMware虚拟机 Ubuntu没有共享文件夹的问题

在虚拟机的Ubuntu系统中&#xff0c;共享文件目录存放在 mnt/hgfs 下面&#xff0c;但是我安装完系统并添加共享文件后发现&#xff0c;在mnt下连/hgfs目录都没有。 注意&#xff1a;使用共享文件目录需要已安装VMtools工具。 添加共享文件目录 一&#xff1a;在超级用户下 可…...

spring使用rabbitmq当rabbitmq集群节点挂掉 spring rabbitmq怎么保证高可用

##spring rabbitmq代码示例 Controller代码 import com.alibaba.fastjson.JSONObject; import com.newland.mi.config.RabbitDMMQConfig; import org.springframework.amqp.core.Message; import org.springframework.amqp.core.MessageProperties; import org.springframewo…...

简单vue3前端打包部署到服务器,动态配置http请求头后端ip方法教程

vue3若依框架前端打包部署到服务器&#xff0c;需要部署到多个服务器上&#xff0c;每次打包会很麻烦&#xff0c;今天教大家一个动态配置请求头api的方法&#xff0c;部署后能动态获取(修改)对应服务器的请求ip 介绍两种方法&#xff0c;如有需要可以直接尝试步骤一&#xff…...

C语言关于溢出和不溢出的判断

通过实验来判断整数溢出&#xff0c;浮点数溢出的情况 #include <stdio.h> #include <limits.h> #include <float.h> int main(void) { // 整数溢出 int int_max INT_MAX; // INT_MAX 是 int 类型的最大值 int int_min INT_MIN; // INT_MIN …...

【NOIP】1998真题解析 luogu-P1008 三连击 | GESP三、四级以上可练习

NOIP 1998 普及组真题&#xff0c;主要考察枚举算法与数位分离。题目要求将 这些数字进行组合&#xff0c;寻找符合特定比例的三位数。这是一个很经典的暴力枚举题。GESP三、四级以上可练习。题目难度⭐⭐☆☆☆&#xff0c;洛谷难度等级普及−。 luogu-P1008 [NOIP 1998 普…...

《生产级性能监控实战:基于 Spring AOP + 消息提醒的智能告警系统设计与实现》

一、引言1.1 痛点场景在生产环境中&#xff0c;性能问题往往比业务缺陷更难以察觉&#xff0c;也更具破坏力。你是否也遇到过以下困境&#xff1a;生产环境性能问题难以发现&#xff1f;接口响应从 200ms 逐渐恶化到 5 秒&#xff0c;用户感知强烈&#xff0c;监控系统却毫无告…...

美团外卖省钱终极指南:如何用自动化脚本每月多省200元

美团外卖省钱终极指南&#xff1a;如何用自动化脚本每月多省200元 【免费下载链接】meituan-shenquan 美团 天天神券 地区活动 自动化脚本 项目地址: https://gitcode.com/gh_mirrors/me/meituan-shenquan 还在为美团天天神券抢不到而烦恼吗&#xff1f;还在因为忘记签到…...

JTCalendar高级功能探索:水平与垂直布局的完整实现指南

JTCalendar高级功能探索&#xff1a;水平与垂直布局的完整实现指南 【免费下载链接】JTCalendar A customizable calendar view for iOS. 项目地址: https://gitcode.com/gh_mirrors/jt/JTCalendar JTCalendar是一款功能强大的iOS自定义日历视图库&#xff0c;提供灵活的…...

G-Helper技术架构解析:华硕笔记本ACPI控制接口的轻量化实现

G-Helper技术架构解析&#xff1a;华硕笔记本ACPI控制接口的轻量化实现 【免费下载链接】g-helper Lightweight, open-source control tool for ASUS laptops and ROG Ally. Manage performance modes, fans, GPU, battery, and RGB lighting across Zephyrus, Flow, TUF, Stri…...

Wan2.1 VAE数据预处理实战:Python爬虫采集的训练数据清洗

Wan2.1 VAE数据预处理实战&#xff1a;Python爬虫采集的训练数据清洗 如果你对Wan2.1 VAE模型感兴趣&#xff0c;想用自己的图片集来训练它&#xff0c;那么你很可能已经遇到了第一个&#xff0c;也是最关键的一个难题&#xff1a;数据从哪里来&#xff1f;又该怎么处理&#…...

零基础5分钟部署AI股票分析师:Ollama本地大模型一键生成专业报告

零基础5分钟部署AI股票分析师&#xff1a;Ollama本地大模型一键生成专业报告 1. 为什么你需要一个本地AI股票分析师 在金融投资领域&#xff0c;及时获取专业分析报告是做出明智决策的关键。但传统方式存在几个痛点&#xff1a; 数据隐私问题&#xff1a;使用在线分析工具需…...

s2-proWeb工具深度体验:响应速度、试听流畅度与下载稳定性评测

s2-proWeb工具深度体验&#xff1a;响应速度、试听流畅度与下载稳定性评测 1. 产品概览 s2-pro是Fish Audio开源的专业级语音合成模型镜像&#xff0c;作为一款专注于文本转语音(TTS)的工具&#xff0c;它提供了两种核心功能模式&#xff1a; 基础语音合成&#xff1a;直接输…...

AI学习方法论--AI费曼学习法:让AI扮演3个角色,把知识刻进脑子

很多人都有这样的经历&#xff1a;刚看完一本书&#xff0c;感觉自己什么都懂了。结果一周以后&#xff0c;别人问你学到了什么&#xff0c;你支支吾吾半天&#xff0c;说不出个所以然。 为什么&#xff1f; 因为你只是"看过"&#xff0c;不是"学会"。 今天…...

丹青幻境问题解决:避讳词设置与角色畸形手指修复指南

丹青幻境问题解决&#xff1a;避讳词设置与角色畸形手指修复指南 1. 引言&#xff1a;AI绘画中的常见挑战 在使用丹青幻境进行角色设计时&#xff0c;许多创作者都会遇到两个典型问题&#xff1a;一是生成的图像中出现不想要的元素&#xff0c;二是角色手指等细节部位出现畸形…...