【蓝桥杯】43692.青蛙跳杯子

embedded/2025/2/3 7:10:41/

题目描述

X 星球的流行宠物是青蛙,一般有两种颜色:白色和黑色。

X 星球的居民喜欢把它们放在一排茶杯里,这样可以观察它们跳来跳去。

如下图,有一排杯子,左边的一个是空着的,右边的杯子,每个里边有一只青蛙。

∗ W W W B B B ∗WWWBBB WWWBBB

其中,
W 字母表示白色青蛙,
B 表示黑色青蛙,
∗ 表示空杯子。

X 星的青蛙很有些癖好,它们只做 3 个动作之一:

跳到相邻的空杯子里。

隔着 1 只其它的青蛙(随便什么颜色)跳到空杯子里。

隔着 2 只其它的青蛙(随便什么颜色)跳到空杯子里。

对于上图的局面,只要 1 步,就可跳成下图局面:

W W W ∗ B B B WWW∗BBB WWWBBB

本题的任务就是已知初始局面,询问至少需要几步,才能跳成另一个目标局面。

输入描述

输入为 2 行,2 个串,表示初始局面和目标局面。我们约定,输入的串的长度不超过 15。

输出描述

输出要求为一个整数,表示至少需要多少步的青蛙跳。

输入输出样例

示例
输入

※WWBB
WWBB※

输出

2

解题思路

先来看看 ∗ W W W B B B ∗WWWBBB WWWBBB 怎么变成 W W W ∗ B B B WWW∗BBB WWWBBB
很简单,第三个 W 的青蛙向左跳了2格,占了 ∗ ∗ 的位置,而跳走后,原来的位置变为 ∗ ∗
在这里插入图片描述
再看看 ∗ W W B B *WWBB WWBB 怎么变为 W W B B ∗ WWBB* WWBB
至少需要两步: ∗ W W B B *WWBB WWBB W W ∗ B B WW*BB WWBB W W B B ∗ WWBB* WWBB

对于已知初始状态和结束状态的题目,简单粗暴的解题思路无非两种,一种枚举,一种遍历,把所有的可能性都试一遍,而找出其中 路径最短 / 步骤最少 的,无疑要使用遍历算法,那么优先考虑 广度优先BFS深度优先DFS

假设起始局面为 ∗ W W B B *WWBB WWBB,目标局面为 W W B B ∗ WWBB* WWBB

  1. 初始时,队列 Q = [[‘ ∗ W W B B *WWBB WWBB’, 0]],集合 aset = {‘ ∗ W W B B *WWBB WWBB’}。
  2. 从队列取出 [‘ ∗ W W B B *WWBB WWBB’, 0],对其应用各种移动方式:
      当移动方式为 1 时,得到新局面 W ∗ W B B W*WBB WWBB,步数变为 1。检查发现 W ∗ W B B W*WBB WWBB 不在 aset 中,将其加入 aset 并把 [‘ W ∗ W B B W*WBB WWBB’, 1] 加入队列 Q。
      类似地,依次应用其他移动方式生成新局面并处理。
  3. 继续从队列中取出元素进行探索,直到找到目标局面 W W B B ∗ WWBB* WWBB,此时输出的步数即为从起始局面到目标局面的最少步数。

  通过这种逐层扩展搜索空间的方式,使用 广度优先搜索BFS 能够保证第一次找到目标状态时所经过的路径是最短的。

算法步骤

  1. 读取用户输入的初始局面和目标局面。
  2. 定义青蛙可能的移动方式。
  3. 使用集合 aset 记录已经访问过的局面,避免重复搜索。
  4. 初始化队列 Q,将初始局面和步数 0 加入队列。
  5. 不断从队列中取出元素,尝试所有可能的移动方式,得到新的局面。
  6. 如果新的局面等于目标局面,输出步数并结束搜索。
  7. 如果新的局面未被访问过,将其加入已访问集合和队列,继续搜索。

代码展示

感谢 @朱恒彤 同学提供的代码。

python">import os
import sys# 从用户输入中读取初始局面和目标局面,start 是起始状态,end 是目标状态
start = input()
end = input()# 定义青蛙可能的移动方式
# 这是一个列表,表示在字符串中可以移动的位数(向右或向左),
# 其中正数表示向右移动,负数表示向左移动。例如,1 表示向右移动 1 格,-2 表示向左移动 2 格
move = [1, -1, 2, -2, 3, -3]# aset 是一个集合,集合的特点是元素具有唯一性,用于记录已经访问过的状态,以避免重复访问。
# 初始时将起始状态加入集合
aset = {start}# 定义广度优先搜索函数
def bfs():# 初始化队列,队列中的每个元素是一个列表,包含当前局面和到达该局面所需的步数# 初始时队列中只有一个元素,即起始状态和对应的步数 0,说明步数是从 0 开始的Q = [[start, 0]]# 当队列不为空时,继续搜索while Q:# 从队列中取出队首元素# 运用了 while Q 循环。只要 Q 不为空,就会从队列中取出一个 old# old 是一个列表,old[0] 是当前局面,old[1] 是到达该局面所需的步数old = Q.pop(0)# 遍历所有可能的移动方式for i in move:# 将当前局面的字符串转换为字符列表,因为字符串是不可变类型,而列表是可变类型,方便进行字符交换操作a = list(old[0])# 获取到达当前局面所需的步数b = old[1]# 找到空位(用 '*' 表示)在字符列表中的索引c = a.index('*')# 计算空位移动后的新索引d = c + i# 检查新索引是否在合法范围内if 0 <= d < len(start):# 交换空位和新索引位置的字符a[c] = a[d]# 将新的字符位置的值转移到 '*' 的位置,把原来 '*' 的位置设置为新的字符a[d] = '*'# 将字符列表转换回字符串,重新形成新的状态字符,得到新的局面e = ''.join(a)# 步数加 1b += 1# 如果新的局面等于目标局面,输出当前步数并结束搜索if e == end:print(b)return# 如果新的局面未被访问过,将其加入已访问集合aset,表示为已访问,并加入队列Q,,表示加入新的局面和对应的步数,然后继续搜索if e not in aset:aset.add(e)Q.append([e, b])# 调用广度优先搜索函数开始搜索
bfs()

http://www.ppmy.cn/embedded/159118.html

相关文章

一文大白话讲清楚webpack基本使用——17——Tree Shaking

文章目录 一文大白话讲清楚webpack基本使用——17——Tree Shaking1. 建议按文章顺序从头看&#xff0c;一看到底&#xff0c;豁然开朗2. 啥叫Tree Shaking3. 什么是死代码&#xff0c;怎么来的3. Tree Shaking的流程3.1 标记3.2 利用Terser摇起来 4. 具体使用方式4.1 适用前提…

Python安居客二手小区数据爬取(2025年)

目录 2025年安居客二手小区数据爬取观察目标网页观察详情页数据准备工作&#xff1a;安装装备就像打游戏代码详解&#xff1a;每行代码都是你的小兵完整代码大放送爬取结果 2025年安居客二手小区数据爬取 这段时间需要爬取安居客二手小区数据&#xff0c;看了一下相关教程基本…

linux下ollama更换模型路径

Linux下更换Ollama模型下载路径指南   在使用Ollama进行AI模型管理时&#xff0c;有时需要根据实际需求更改模型文件的存储路径。本文将详细介绍如何在Linux系统中更改Ollama模型的下载路径。 一、关闭Ollama服务   在更改模型路径之前&#xff0c;需要先停止Ollama服务。…

【前端学习路线】前端生态 详细知识点学习路径(附学习资源)

&#x1f4da;学习资源&#xff1a; 前端开发&#xff1a;零基础入门到项目实战 >> 前端开发&#xff1a;边学边练 >> 原学习路径下载 >>

探索高效图像识别:基于OpenCV的形状匹配利器

探索高效图像识别&#xff1a;基于OpenCV的形状匹配利器-CSDN博客

Ubuntu 下 nginx-1.24.0 源码分析 ngx_debug_init();

目录 ngx_debug_init() 函数&#xff1a; NGX_LINUX 的定义&#xff1a; ngx_debug_init() 函数&#xff1a; ngx_debug_init() 函数定义在 src\os\unix 目录下的 ngx_linux_config.h 中 #define ngx_debug_init() 也就是说这个环境下的 main 函数中的 ngx_debug_init() 这…

mysql.sock.lock 导致mysql重启失败

背景 今天公司物业断电&#xff0c;导致机房服务器停电宕机&#xff0c;所有的服务都得重启。本着mysql实例都做了服务自启动&#xff0c;所以没有太担心影响开发的日常工作。但是今天一上班开发就找来&#xff0c;各种服务都没起来有问题&#xff0c;数据库连不上。马上登陆数…

语音识别播报人工智能分类垃圾桶(论文+源码)

2.1 需求分析 本次语音识别播报人工智能分类垃圾桶&#xff0c;设计功能要求如下∶ 1、具有四种垃圾桶&#xff0c;分别为用来回收厨余垃圾&#xff0c;有害垃圾&#xff0c;可回收垃圾&#xff0c;其他垃圾。 2、当用户语音说出“旧报纸”&#xff0c;“剩菜”等特定词语时…