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

人工智能(Educoder)-- 搜索技术 -- 启发式搜索

任务描述

本关任务:八数码问题是在一个3×3的棋盘上有1−8位数字随机分布,以及一个空格,与空格相连的棋子可以滑动到空格中,问题的解是通过空格滑动,使得棋盘转化为目标状态,如下图所示。

为了简化问题的输入,首先将空格用数字0表示,然后将3×3的棋盘用9位长的字符串表示,则上图的初始状态为724506831,目标状态为012345678,本关卡所有目标状态均为012345678,也保证初始状态到目标状态有解。

对于上图的初始状态,将数字2移动到空格,称之为u操作(空格上移),将数字3移动到空格,称之为d操作(空格下移),将数字5移动到空格,称之为l操作(空格左移),将数字6移动到空格,称之为r操作(空格右移),则一个合法移动路径为lurdrdllurrdllurrulldrrull。

相关知识

为了完成本关任务,你需要掌握:1.评估函数,2.贪婪最佳优先搜索,3.A*搜索:缩小总评估代价,4.求解思路。

评估函数

在有信息搜索 Informed Search 策略中,常使用的是最佳优先搜索 Best First Search ,它的结点扩展是基于评估函数值f(n)选择的。评估函数被看做是代价估计,因此代价最低的结点最先被选择扩展。

对f(n)的选择决定了搜索策略,大部分的最佳优先搜索算法的f(n)由启发式函数h(n)构成:

h(n)=结点n到目标的最小代价路径的代价估计值

贪婪最佳优先搜索

贪婪最佳优先搜索 Greedy Best-First Search 试图扩展距离目标结点最近的结点,原因是这种策略可能可以非常快的找到解,因此,贪婪最佳优先搜索只使用启发式信息,即f(n)=h(n)。

A*搜索:缩小总评估代价

A* 搜索(A 星搜索)是最广为人知的最佳优先搜索,它对结点n的代价评估结合了g(n),即到达此结点n已经花费的路径代价,和h(n),即从该结点n到目标结点所花代价。

f(n)=g(n)+h(n)

由于g(n)是从开始结点到结点n的路径代价,而h(n)是从结点n到目标结点的最小路径代价的估计值因此:

f(n)=经过结点n的最小代价解的估计代价

所以,要寻找最小代价的解,首先扩展的是g(n)+h(n)值最小的结点。可以发现,A* 搜索算法与一致代价搜索算法类似,区别是 A* 搜索算法使用g(n)+h(n)而不是g(n)。

求解思路

该问题是将与空格相连的数字移动到空格的位置上,也就相当于将空格移动到与之相连的位置,因此,以空格为当前结点,扩展结点可能为上下左右四个相连的位置,若使用一般的搜索算法,可能陷入无限搜索中,永远搜不到目标解,而 A* 搜索算法则能非常好的将搜索过程导向求解目标。

问题给的是字符串数据724506831,可以还原成如下形式:

那么空格的l移动操作即为下标4和下标3上所对应的数字的交换,分别为0和5,交换后的新的状态为:

以此类推,空格的lrud各操作均可用以上的交换过程表达。

A* 算法的重中之重就是启发式函数h(n)的设计,不同的设计方法可能产生不同的求解路径。在这里,可以选择欧氏距离作为评估函数值:除0之外,各个数字在当前状态的下标与目标状态的下标的绝对值之和。例如:当前状态为123456780,目标状态为:012345678,数字1的下标分别为0和1,数字2的下标分别为1和2,...,数字8的下标分别为7和8,则当前状态与目标状态的评估值为h(n)=abs(1−2)+abs(2−3)+⋯+abs(7−8)=8。

编程要求

本关的编程任务是补全右侧代码片段 salvePuzzle 、 calcDistH 和 moveMap 中 Begin 至 End 中间的代码,具体要求如下:

  • 在 salvePuzzle 中,根据输入参数init(初始状态,如724506831)和targ(目标状态,均为012345678),实现 A* 搜索算法,返回八数码问题的移动路径,如上图的移动路径:lurdrdllurrdllurrulldrrull。

  • 在 calcDistH 中,计算当前状态(参数srcmap,如724506831)到目标状态(参数destmap,如012345678)的启发式函数值h(n),并返回h(n)。

  • 在 moveMap 中,实现行动转换,并返回下一个状态,例如当前状态为参数curmap=724506831,当前 8 数码状态curmap中空格 0 的位置索引i=4,移动空格到位置j=3,则返回的新状态为newmap=724056831。

测试说明

平台将自动编译补全后的代码,并生成若干组测试数据,接着测试程序会调用上述函数,并判断函数返回的路径是否为合法解,若是则输出 Accepted 表示程序正确,否则程序错误。

以下是平台的测试样例:

测试输入: 724506831

预期输出: Accepted

代码
# -*- coding:utf-8 -*-class Solution:def salvePuzzle(self, init, targ):''' 求解8数码问题参数:init - 初始状态 例如'123046758'targ - 目标状态 均为'012345678'返回值:clf - 由udlr组成的移动路径字符串'''#请在这里补充代码,完成本关任务#********** Begin **********#clf = ''  # 初始化移动路径字符串state_open = []  # 初始化开放列表state_close = []  # 初始化关闭列表state_open.append([init,99,'test',init,0])  # 将初始状态加入开放列表fn = 2  # 初始化启发式函数的权重flag = 1  # 初始化标志位while True:cur_state = state_open.pop(0)  # 取出开放列表中的第一个状态state_close.append(cur_state)  # 将当前状态加入关闭列表if cur_state[0] == targ:  # 如果当前状态等于目标状态while 1:clf += cur_state[2]  # 将当前状态的移动方向加入移动路径字符串if cur_state[3] == init:  # 如果当前状态的父状态等于初始状态breakfor id,item in enumerate(state_close[1:]):  # 遍历关闭列表中的状态if item[0] == cur_state[3]:  # 如果找到父状态cur_state = item  # 更新当前状态为父状态return  clf[::-1]  # 返回逆序的移动路径字符串i = cur_state[0].find('0')  # 找到空格0的位置索引flag = 1  # 重置标志位if str(i) not in '036':  # 如果空格0不在第一行、第三行和第六行tmp_map = self.moveMap(cur_state[0],i,i-1)  # 尝试将空格0向左移动if tmp_map not in [tmp[0] for tmp in state_close]:  # 如果新状态不在关闭列表中for id,item in enumerate(state_open):  # 遍历开放列表中的状态if item[0] == tmp_map:  # 如果找到新状态if item[1] + item[4] > self.calcDistH(tmp_map,targ) + cur_state[4] + fn:  # 如果新状态的代价大于当前状态的代价state_open[id] = [tmp_map,self.calcDistH(tmp_map,targ),'l',cur_state[0],cur_state[4]+fn]  # 更新开放列表中的状态flag = 0  # 设置标志位为0breakbreakif flag == 1:  # 如果标志位为1state_open.append([tmp_map,self.calcDistH(tmp_map,targ),'l',cur_state[0],cur_state[4]+fn])  # 将新状态加入开放列表flag = 1  # 重置标志位if str(i) not in '258':  # 如果空格0不在第二行、第五行和第八行tmp_map = self.moveMap(cur_state[0],i,i+1)  # 尝试将空格0向右移动if tmp_map not in [tmp[0] for tmp in state_close]:  # 如果新状态不在关闭列表中for id,item in enumerate(state_open):  # 遍历开放列表中的状态if item[0] == tmp_map:  # 如果找到新状态if item[1] + item[4] > self.calcDistH(tmp_map,targ) + cur_state[4] + fn:  # 如果新状态的代价大于当前状态的代价state_open[id] = [tmp_map,self.calcDistH(tmp_map,targ),'r',cur_state[0],cur_state[4]+fn]  # 更新开放列表中的状态flag = 0  # 设置标志位为0breakbreakif flag ==1:  # 如果标志位为1state_open.append([tmp_map,self.calcDistH(tmp_map,targ),'r',cur_state[0],cur_state[4]+fn])  # 将新状态加入开放列表flag = 1  # 重置标志位if i-3>=0:  # 如果空格0不在最左边的三列tmp_map = self.moveMap(cur_state[0],i,i-3)  # 尝试将空格0向上移动if tmp_map not in [tmp[0] for tmp in state_close]:  # 如果新状态不在关闭列表中for id,item in enumerate(state_open):  # 遍历开放列表中的状态if item[0] == tmp_map:  # 如果找到新状态if item[1] + item[4] > self.calcDistH(tmp_map,targ) + cur_state[4] + fn:  # 如果新状态的代价大于当前状态的代价state_open[id] = [tmp_map,self.calcDistH(tmp_map,targ),'u',cur_state[0],cur_state[4]+fn]  # 更新开放列表中的状态flag = 0  # 设置标志位为0breakbreakif flag ==1:  # 如果标志位为1state_open.append([tmp_map,self.calcDistH(tmp_map,targ),'u',cur_state[0],cur_state[4]+fn])  # 将新状态加入开放列表flag = 1  # 重置标志位if i+3<=8:  # 如果空格0不在最右边的三列tmp_map = self.moveMap(cur_state[0],i,i+3)  # 尝试将空格0向下移动if tmp_map not in [tmp[0] for tmp in state_close]:  # 如果新状态不在关闭列表中for id,item in enumerate(state_open):  # 遍历开放列表中的状态if item[0] == tmp_map:  # 如果找到新状态if item[1] + item[4] > self.calcDistH(tmp_map,targ) + cur_state[4] + fn:  # 如果新状态的代价大于当前状态的代价state_open[id] = [tmp_map,self.calcDistH(tmp_map,targ),'d',cur_state[0],cur_state[4]+fn]  # 更新开放列表中的状态flag = 0  # 设置标志位为0breakbreakif flag ==1:  # 如果标志位为1state_open.append([tmp_map,self.calcDistH(tmp_map,targ),'d',cur_state[0],cur_state[4]+fn])  # 将新状态加入开放列表state_open.sort(key=lambda x : x[1] + x[4])  # 根据代价对开放列表进行排序#********** End **********#def calcDistH(self, src_map, dest_map):'''启发式函数h(n)参数:src_map  - 当前8数码状态dest_map - 目标8数码状态返回值:clf - 当前状态到目标状态的启发式函数值'''#请在这里补充代码,完成本关任务#********** Begin **********#if src_map is None or dest_map is None:return 0 clf = 0for i in range(9):clf += abs(int(src_map[i])-int(dest_map[i]))return clf#********** End **********#def moveMap(self, cur_map, i, j):'''状态转换(交换位置i和j)参数:cur_map - 当前8数码状态i - 当前8数码状态中空格0的位置索引j - 将空格0的位置i移动到位置j,位置j移动到位置i返回值:clf - 新的8数码状态'''#请在这里补充代码,完成本关任务#********** Begin **********#if i>j:i,j=j,itmp_i = cur_map[i]tmp_j = cur_map[j]tmp_map = cur_map[:i]+tmp_j+cur_map[i+1:j]+tmp_i+cur_map[j+1:]return tmp_map#********** End **********#

相关文章:

人工智能(Educoder)-- 搜索技术 -- 启发式搜索

任务描述 本关任务&#xff1a;八数码问题是在一个33的棋盘上有1−8位数字随机分布&#xff0c;以及一个空格&#xff0c;与空格相连的棋子可以滑动到空格中&#xff0c;问题的解是通过空格滑动&#xff0c;使得棋盘转化为目标状态&#xff0c;如下图所示。 为了简化问题的输…...

计算平均分 javascript

养成好习惯&#xff1a;先写注释再写代码 基础版&#xff1a;直接写逻辑&#xff08;平均分总和/个数&#xff09; // 求平均分 var scores [60, 55, 80, 33, 75, 100]; // 求和,相除 var sum 0; var avg;for (var i 0; i < 6; i) {sum scores[i]; }avg sum / 6; con…...

Redis入门到实战-第三弹

Redis入门到实战 Redis数据类型官网地址Redis概述Redis数据类型介绍更新计划 Redis数据类型 官网地址 声明: 由于操作系统, 版本更新等原因, 文章所列内容不一定100%复现, 还要以官方信息为准 https://redis.io/Redis概述 Redis是一个开源的&#xff08;采用BSD许可证&#…...

AnyGo for Mac最新激活版:位置模拟软件打破地域限制

AnyGo for Mac&#xff0c;一款专为Mac用户打造的位置模拟软件&#xff0c;让您能够轻松打破地域限制&#xff0c;畅享无限可能。 软件下载&#xff1a;AnyGo for Mac v7.0.0最新激活版 通过AnyGo&#xff0c;您可以随时随地模拟出任何地理位置&#xff0c;无论是国内热门景点还…...

【Mysql数据库基础07】DDL 数据定义语言

Data Definition Language 1 库的操作1.1 create 创建1.2 alter 修改1.3 drop 删除 2 表的操作2.1 表的创建2.2 表的修改2.2.1 修改表名2.2.2 修改列名2.2.3 修改列的类型和约束2.2.4 添加列2.2.5 删除列 2.3 表的删除2.4 表的复制 3 练习 1 库的操作 1.1 create 创建 create…...

数据库及中表的创建和管理

目录 创建数据库 使用数据库(使用,查看信息) 修改数据库(删除,修改)...

git笔记之撤销、回退、reset方面的笔记

git笔记之撤销、回退、reset方面的笔记 code review! 文章目录 git笔记之撤销、回退、reset方面的笔记1.git 已经commit了&#xff0c;还没push&#xff0c;如何撤销到初始状态git reset --soft HEAD~1git reset HEAD~1&#xff08;等同于 git reset --mixed HEAD~1&#xff0…...

【中间件】docker数据卷

&#x1f4dd;个人主页&#xff1a;五敷有你 &#x1f525;系列专栏&#xff1a;中间件 ⛺️稳中求进&#xff0c;晒太阳 1.数据卷&#xff08;容器数据管理&#xff09; 修改nginx的html页面时&#xff0c;需要进入nginx内部。并且因为内部没有编辑器&#xff0c;修改…...

【3D reconstruction 学习笔记 第二部】

三维重建 3D reconstruction 4. 三维重建与极几何三角化&#xff08;线性解法&#xff09;三角化&#xff08;非线性解法&#xff09;多视图几何极几何极几何约束基础矩阵估计 5. 双目立体视觉重建6. 多视图重建7. SFM 系统设计8. SLAM系统设计 4. 三维重建与极几何 三角化&…...

【CSP试题回顾】202109-1-数组推导(优化)

CSP-202109-1-数组推导 解题代码 #include <iostream> #include <vector> #include <algorithm> using namespace std;long long n, sumMax,sumMin;int main() {cin >> n;vector<long long>arr(n);for (size_t i 0; i < n; i){cin >>…...

Redis - 高并发场景下的Redis最佳实践_翻过6座大山

文章目录 概述6座大山之_缓存雪崩 &#xff08;缓存全部失效&#xff09;缓存雪崩的两种常见场景如何应对缓存雪崩&#xff1f; 6座大山之_缓存穿透&#xff08;查询不存在的 key&#xff09;缓存穿透的原因解决方案1. 数据校验2. 缓存空值3. 频控4. 使用布隆过滤器 6座大山之_…...

数字乡村发展策略:科技引领农村实现跨越式发展

随着信息技术的迅猛发展和数字经济的崛起&#xff0c;数字乡村发展策略已经成为引领农村实现跨越式发展的重要手段。科技的力量正在深刻改变着传统农业的生产方式、农村的社会结构以及农民的生活方式&#xff0c;为农村经济发展注入了新的活力和动力。本文将从数字乡村的内涵、…...

TCP重传机制详解——04FACK

文章目录 TCP重传机制详解——04FACK什么是FACKFACK的发展为什么要引入FACK实战抓包讲解开启FACK场景&#xff0c;且达到dup ACK门限值开启FACK场景&#xff0c;未达到dup ACK门限值 为什么要淘汰FACK总结REF TCP重传机制详解——04FACK 什么是FACK FACK的全称是forward ackn…...

安卓Java面试题 206- 210

206. 简述如何统计Activity的工作时间 ?如何统计Activity启动所用的时间? 可以通过分析Log得到(这个就是DDMS的那个Log)。 当我们点击触摸时会了类似以下的Log A: 03-06 03:36:47.865: VERBOSE/InputDevice(2486): ID[0]=0(0) Dn (0=>1) 03-06 03:36:47.865: INFO/Powe…...

huggingface的transformers训练bert

目录 理论 实践 理论 https://arxiv.org/abs/1810.04805 BERT&#xff08;Bidirectional Encoder Representations from Transformers&#xff09;是一种自然语言处理&#xff08;NLP&#xff09;模型&#xff0c;由Google在2018年提出。它是基于Transformer模型的预训练方法…...

计算机三级——网络技术(综合题第五题)

第一题 填写路由器RG的路由表项①至④。 目的网络&#xff0f;掩码长度输出端口输出端口172.19.63.192&#xff0f;30S0(直接连接)172.19.63.188&#xff0f;30S1(直接连接) 路由器RG的S0的IP地址是172.19.63.193&#xff0c;路由器RE的S0的IP地址是172.19.63.194。 【解析】…...

C#使用ASP.NET Core Razor Pages构建网站(三)

上一篇文章了解Razor Pages 链接&#xff1a;C#使用ASP.NET Core Razor Pages构建网站&#xff08;二&#xff09; 接下来继续了解ASP.NET Core Razor Pages构建网站的后续内容 一、将Entity Framework Core配置为服务 要在 ASP.NET Core 项目中配置 Entity Framework Core 服…...

R语言迅速计算多基因评分(PRS)

Polygenic Risk Scores in R 最朴素的理解PRS&#xff1a; GWAS分析结果中&#xff0c;有每个SNP的beta值、se值、P值&#xff0c;因为GWAS分析中将SNP变为0-1-2编码&#xff0c;所以这些显著的SNP的beta值&#xff0c;就可以用于预测。 比如&#xff1a;GWAS分析中&#xf…...

蓝桥杯刷题_day3

文章目录 DAY301字串判断闰年Fibonacci数列圆的面积序列求和 DAY3 01字串 【题目描述】 对于长度为5位的一个01串&#xff0c;每一位都可能是0或1&#xff0c;一共有32种可能。它们的前几个是&#xff1a; 00000 00001 00010 00011 00100 请按从小到大的顺序输出这32种01串。…...

Dubbo源码解析-Provider服务暴露Export源码解析

上篇我们介绍了ServiceBean初始化和依赖注入过程&#xff0c;地址如下 Dubbo源码-Provider服务端ServiceBean初始化和属性注入-CSDN博客 本文主要针Dubbo服务端服务Export过程&#xff0c;从dubbo源码角度进行解析。 Dubbo 服务端暴露细节流程比较长&#xff0c;也是面试过程中…...

Java 语言特性(面试系列2)

一、SQL 基础 1. 复杂查询 &#xff08;1&#xff09;连接查询&#xff08;JOIN&#xff09; 内连接&#xff08;INNER JOIN&#xff09;&#xff1a;返回两表匹配的记录。 SELECT e.name, d.dept_name FROM employees e INNER JOIN departments d ON e.dept_id d.dept_id; 左…...

VB.net复制Ntag213卡写入UID

本示例使用的发卡器&#xff1a;https://item.taobao.com/item.htm?ftt&id615391857885 一、读取旧Ntag卡的UID和数据 Private Sub Button15_Click(sender As Object, e As EventArgs) Handles Button15.Click轻松读卡技术支持:网站:Dim i, j As IntegerDim cardidhex, …...

华为云Flexus+DeepSeek征文|DeepSeek-V3/R1 商用服务开通全流程与本地部署搭建

华为云FlexusDeepSeek征文&#xff5c;DeepSeek-V3/R1 商用服务开通全流程与本地部署搭建 前言 如今大模型其性能出色&#xff0c;华为云 ModelArts Studio_MaaS大模型即服务平台华为云内置了大模型&#xff0c;能助力我们轻松驾驭 DeepSeek-V3/R1&#xff0c;本文中将分享如何…...

Unity | AmplifyShaderEditor插件基础(第七集:平面波动shader)

目录 一、&#x1f44b;&#x1f3fb;前言 二、&#x1f608;sinx波动的基本原理 三、&#x1f608;波动起来 1.sinx节点介绍 2.vertexPosition 3.集成Vector3 a.节点Append b.连起来 4.波动起来 a.波动的原理 b.时间节点 c.sinx的处理 四、&#x1f30a;波动优化…...

React---day11

14.4 react-redux第三方库 提供connect、thunk之类的函数 以获取一个banner数据为例子 store&#xff1a; 我们在使用异步的时候理应是要使用中间件的&#xff0c;但是configureStore 已经自动集成了 redux-thunk&#xff0c;注意action里面要返回函数 import { configureS…...

Linux离线(zip方式)安装docker

目录 基础信息操作系统信息docker信息 安装实例安装步骤示例 遇到的问题问题1&#xff1a;修改默认工作路径启动失败问题2 找不到对应组 基础信息 操作系统信息 OS版本&#xff1a;CentOS 7 64位 内核版本&#xff1a;3.10.0 相关命令&#xff1a; uname -rcat /etc/os-rele…...

R语言速释制剂QBD解决方案之三

本文是《Quality by Design for ANDAs: An Example for Immediate-Release Dosage Forms》第一个处方的R语言解决方案。 第一个处方研究评估原料药粒径分布、MCC/Lactose比例、崩解剂用量对制剂CQAs的影响。 第二处方研究用于理解颗粒外加硬脂酸镁和滑石粉对片剂质量和可生产…...

CRMEB 中 PHP 短信扩展开发:涵盖一号通、阿里云、腾讯云、创蓝

目前已有一号通短信、阿里云短信、腾讯云短信扩展 扩展入口文件 文件目录 crmeb\services\sms\Sms.php 默认驱动类型为&#xff1a;一号通 namespace crmeb\services\sms;use crmeb\basic\BaseManager; use crmeb\services\AccessTokenServeService; use crmeb\services\sms\…...

Kafka主题运维全指南:从基础配置到故障处理

#作者&#xff1a;张桐瑞 文章目录 主题日常管理1. 修改主题分区。2. 修改主题级别参数。3. 变更副本数。4. 修改主题限速。5.主题分区迁移。6. 常见主题错误处理常见错误1&#xff1a;主题删除失败。常见错误2&#xff1a;__consumer_offsets占用太多的磁盘。 主题日常管理 …...

第一篇:Liunx环境下搭建PaddlePaddle 3.0基础环境(Liunx Centos8.5安装Python3.10+pip3.10)

第一篇&#xff1a;Liunx环境下搭建PaddlePaddle 3.0基础环境&#xff08;Liunx Centos8.5安装Python3.10pip3.10&#xff09; 一&#xff1a;前言二&#xff1a;安装编译依赖二&#xff1a;安装Python3.10三&#xff1a;安装PIP3.10四&#xff1a;安装Paddlepaddle基础框架4.1…...