题目描述:

假设有一只兔子,有4个排成一排的洞,编号为1和4。兔子每天晚上跳到相邻的一个洞里住,2号洞可以跳1号和3号洞,4号洞只能跳3号洞。而猎人每天白天检查其中的一个洞。猎人告诉你每天检查的洞的编号,分析一下是否一定能抓到兔子。如果能抓到,找出最优路径。

这道题思路:想办法把兔子逼到最后一个洞或者第一个洞,这样它下一步只只有一个洞可跳自然就找到了,列举探索的思路也很重要,要分别列出当前可能藏的洞和当前没找到下一次可能藏的洞,找准这两个变量很关键,最终是要把兔子逼到第一个洞或者最后一个洞,所以下一次可能藏的洞会越来越少,所以猎人选择洞的时候也要考虑这一点(猎人选择所要找的洞,下一次可能藏的洞相比找之前可能藏的洞应该会少,直到最终剩下一个洞)。

例如:先选择1,兔子不在1,那么当前可能在的洞2,3,4,下一次可能藏的洞为1,2,3,4。这样跟下一次比较洞没有减少。所以想着第一步不应该选1。按照每找一次下一次可能藏的洞越来越少思路。实际我们代码中找的时候肯定是按顺序找,列出所有可能找的过程,所以我们代码就要决定哪一步是不需要的,找准条件筛选。

BFS(广度优先算法)

此题的思想和BFS(广度优先算法)类似,简单说一下。BFS(广度优先算法)是一个针对图和树的遍历算法。简单的说,BFS是从根节点开始,沿着树的宽度遍历树的节点,如果所有节点均被访问,则算法中止;最初用于解决迷宫最短路径和网络路由等问题。

BFS操作步骤如下: 
1、把起始点放入queue; 
2、重复下述2步骤,直到queue为空为止: 
1) 从queue中取出队列头的点;并删除队列首节点。
2) 找出与此点邻接的且尚未遍历的点,进行标记,然后全部放入queue中。

使用该算法关键的数据结构为队列。新加入的节点一般要是未处理过的,所以某些情况下最初要对所有节点进行标记。 (1)将起始节点1放入队列中,标记为已遍历: 
(2)从queue中取出队列头的节点1,找出与节点1邻接的节点2,3,标记为已遍历,然后放入queue中。 
(3)从queue中取出队列头的节点2,找出与节点2邻接的节点1,4,5,由于节点1已遍历,排除;标记4,5为已遍历,然后放入queue中。以此类推.........

要标志节点是否访问过,用数组是一种很快速的方法,但有时数据量太大,很难用一个大数组来记录时,采用hash,set是最好的做法。实际上visit数组在这里也是充当hash,set的作用。python中暂时采用集合set。还可以利用字典dict标记(充当hash)。

猎人抓兔子代码如下:

import queuedef get_new_set_hole(search_hole, cur_hole):""":param search_hole: 要寻找的洞:param cur_hole: 当前兔子可能在的洞:return:"""# 利用集合代表当查看search_hole后,没有抓到兔子,兔子可能藏身的洞set_hole = set()# 在当前可能存在的洞找相邻的洞即为下一次可能藏身的洞for hole in cur_hole:# 右邻的洞,没有抓到兔子,所以!=search_holeif hole+1 != search_hole and hole+1 <= 4:set_hole.add(hole+1)# 左邻的洞if hole-1 != search_hole and hole-1 >= 1:set_hole.add(hole-1)return set_holedef main():"""1.首先将初始情况加入队列,当队列不为空时:2.如果已经得到了结果,那就结束,跳转到(7.)3.取出队列的第一个值4.分别检查4个洞5.如果检查之后兔子的藏身洞变少,那就将这个洞加入到队列中6.如果检查后兔子没有藏身之处,则已经找到结果,将结果赋值给path同时设置已找到结果标志,并跳出循环7.输出最后记录的结果8.根据得到的结果,找出每一步后兔子藏身之处"""queue_hole = queue.Queue()# 记录最终的找寻过程path = []# 找到就退出循环标志flag = False# 三个参数分别表猎人要找的洞,当前可能藏身的洞,空列表记录猎人找洞的记录# 初始状态还没开始找,所以暂时赋下面的值,第一个参数一般是1-4循环尝试,# 这里初始赋值随便赋一个不影响的值queue_hole.put((0, {1, 2, 3, 4}, []))while not queue_hole.empty():if flag:breakcur, cur_hole_set, record = queue_hole.get()for hole in range(1, 5):copy_record = record[:]next_hole_set = get_new_set_hole(hole, cur_hole_set)if len(next_hole_set) <= len(cur_hole_set):copy_record.append(hole)queue_hole.put((hole, next_hole_set, copy_record))if not next_hole_set:record.append(hole)path = copy_recordflag = Truebreakprint(path)

例子:LeetCode 127 单词接龙

题目描述:

字典wordList中从单词beginWord和endWord的转换序列是一个按下述规格形成的序列beginWord -> s1 -> s2 -> ... -> sk:
每一对相邻的单词只差一个字母。
对于 1 <= i <= k 时,每个 si 都在 wordList 中。注意,beginWord 不需要在 wordList 中。sk == endWord
给你两个单词beginWord和endWord和一个字典wordList,返回从beginWord 到endWord的最短转换序列 中的 单词数目。如果不存在这样的转换序列,返回 0 。

要求:①每次只能变换一个字母。②每个字符串长度相同
③每次转换的字符串必须在wordList中。④如果没有这种转换,返回0。⑤没有重复的

示例:

输入:beginWord = "hit", endWord = "cog", wordList = ["hot", "dot", "dog", "lot", "log", "cog"]
输出:5
解释:一个最短转换序列是 "hit" -> "hot" -> "dot" -> "dog" -> "cog", 返回它的长度 5。

输入:beginWord = "hit", endWord = "cog", wordList = ["hot", "dot", "dog", "lot", "log"]
输出:0
解释:endWord "cog" 不在字典中,所以无法进行转换。

解题思路

1、本题要求的是最短转换序列的长度,看到最短首先想到的就是广度优先搜索。想到广度优先搜索自然而然的就能想到图,但是本题并没有直截了当的给出图的模型,因此我们需要把它抽象成图的模型。
2、我们可以把每个单词都抽象为一个点,如果两个单词可以只改变一个字母进行转换,那么说明他们之间有一条双向边。因此我们只需要把满足转换条件的点相连,就形成了一张图。
3、基于该图,我们以 beginWord 为图的起点,以 endWord 为终点进行广度优先搜索,寻找 beginWord 到 endWord 的最短路径。

由图可得显然有两条路径满足最短路径。

本题跟二叉树的层次遍历类似,想像有一颗二叉树,广度优先搜索就是把二叉树拆成一层一层的,广度优先。(深度优先搜索就是直接一路找到最下面,如果没找到然后再返回来,深度优先)。

因为此题只要求最短路径长度,所以只要遍历到该层时及时记录该层的层数(深度deep)即可。所以差不多就是个找寻满足条件的单词的问题,找到单词之后及时入队列和出队列。

按照分层思路来:那么每层满足条件的单词和层数如下:同一个单词出现在两层因为不止一条路径

hit    1    i变为o 到2
hot   2    h变为d和l到 3
dot   3    d变为l,但lot在第三层已经访问过了,所以不到4,t变为g, 到4
lot    3    t变为g 到4 ,由于l可以变为d,但是dot访问过了。所以4没有dot
dog  4    ..............
log   4
cog  5

import queuedef word_chain(begin_word, end_word, word_list):""":param begin_word: 开始单词:param end_word: 结束单词:param word_list: 单词表:return:"""if end_word not in word_list:return 0# 构造一个字典,key为'*ot','h*t','ho*'这样的形式(key为word_list中单词变化而来)# 然后把满足只变化一个字母的单词归并到同一个key的value中。# 例如:每个单词都有len(word)中形式,hot: *ot, h*t, ho*,分别当做key,然后然后选取满足条件的value# {'*ot': ['hot', 'dot', 'lot'], 'h*t': ['hot'], 'ho*': ['hot']}word_dict = dict()for word in word_list:for i in range(len(word)):key = "{0}*{1}".format(word[:i], word[i+1:])if key in word_dict:word_dict[key].append(word)else:word_dict[key] = [word]queue_data = queue.Queue()queue_data.put((begin_word, 1))# 集合标记单词是否访问过visited = set()while not queue_data.empty():word, steps = queue_data.get()print(word, steps)if word not in visited:visited.add(word)if word == end_word:return stepsfor i in range(len(word)):s = "{0}*{1}".format(word[:i], word[i+1:])for j in word_dict.get(s, []):# 如果j在visited中,说明j已经被访问过了,不需要再次进行访问。if j not in visited:queue_data.put((j, steps + 1))return 0

猎人抓兔子 - (广度优先算法)相关推荐

  1. 2019深信服笔试 —— 猎人抓兔子

    2019深信服笔试 -- 猎人抓兔子 题目描述: 假设兔子有n个排成一排的洞,编号为1和n.兔子每天晚上跳到相邻的一个洞里住,而猎人每天白天检查其中的一个洞.猎人告诉你每天检查的洞的编号,希望你分析一 ...

  2. 猎人抓兔子的bfs搜索解法

    有五个山洞,一字排开,一只兔子住在某个洞,每天晚上会换住到相邻的洞中,一个猎人只能每天早上去一个洞,问怎样的检查序列能确保抓到兔子. 这个问题,可以说是一个智力题了,当然我的智力没有达标,所以没有想出 ...

  3. 【经典算法】:狐狸抓兔子问题

    前言 问题见百度 狐狸抓兔子问题 代码 全在注释里面了,没啥好说的 // 狐狸找兔子问题 // author:seen // time:2015-09-20#include <iostream& ...

  4. 浅谈网络爬虫中广度优先算法和代码实现

    前几天给大家分享了网络爬虫中深度优先算法的介绍及其代码实现过程,没来得及上车的小伙伴们可以戳这篇文章--浅谈网络爬虫中深度优先算法和简单代码实现.今天小编给大家分享网络爬虫中广度优先算法的介绍及其代码 ...

  5. BZOJ1001 狼抓兔子 终于过了!

    时间来不及了,先贴代码吧!有时间再写. 好苦逼啊,WA了若干次,还有一次RE,一次TLE. 虽然主要运用的算法和资料都由师兄提供了.还是太弱了,太天真了. 首先,数据范围就WA了,RE了,TLE了. ...

  6. 狼抓兔子(HYSBZ-1001)

    Problem Description 现在小朋友们最喜欢的"喜羊羊与灰太狼",话说灰太狼抓羊不到,但抓兔子还是比较在行的, 而且现在的兔子还比较笨,它们只有两个窝,现在你做为狼王 ...

  7. matlab狗抓兔子,怎样训成年犬捉兔子-怎样训狗抓兔子

    我的格力犬五六个月了怎样训练它捉兔子 第一:训练幼犬猎兔法:为了训练幼犬追踪猎兔,开始,可由一人抱着死免奔跑,然后放开幼犬追捕.训练幼犬猎兔法:为了训练幼犬追踪猎兔,开始,可由一人抱着死免奔跑,然后放 ...

  8. bzoj1001狼抓兔子

    Description 现在小朋友们最喜欢的"喜羊羊与灰太狼",话说灰太狼抓羊不到,但抓兔子还是比较在行的, 而且现在的兔子还比较笨,它们只有两个窝,现在你做为狼王,面对下面这样一 ...

  9. bzoj 1001狼抓兔子

    1001: [BeiJing2006]狼抓兔子 Time Limit: 15 Sec   Memory Limit: 162 MB Submit: 15622   Solved: 3771 [ Sub ...

最新文章

  1. oracle触发和存储过程,Oracle存储过程与触发器
  2. 【LeetCode笔记】3. 无重复字符的最长子串(JAVA、滑动窗口、字符串)
  3. xmlhttprequest 跨域_跨域资源共享(CORS)安全性
  4. eclipse加速之禁用JS、jsp等文件的语法验证
  5. 63 SD配置-交货凭证配置-定义交货的项目类别
  6. GoldenGate组态(四)它veridata组态
  7. 豪宅周边5家盒马却不配送?盒马回应...
  8. C++调用matlab接口
  9. vc浏览器_【36氪基金X一刻】零基础VC/PE行研标准班7月10日线上开课
  10. java Web常用过滤器
  11. 基于微信小程序做了个交友小程序
  12. LINUX虚拟机安装增强功能时报错:/sbin/mount.vboxsf: mounting failed with the error: No such device
  13. 汉高澳大利亚sinox2014电影播放flash最好的办法是安装游戏windows文本firefox
  14. php 模拟蜘蛛,PHP实现使用CURL模拟百度蜘蛛进行采集
  15. SDHC ADMA和SDMA区别
  16. !Latex Error: File ‘XXXXX.sty‘ not found.
  17. 用ENSP华为模拟器做图书馆得网络配置和设计
  18. (超详细的新手教程)怎么下载JDK包?
  19. 什么是赋范线性空间、内积空间,度量空间,希尔伯特空间
  20. 【Linux上分之路】第十二篇:Linux三剑客grep、sed、awk

热门文章

  1. 90个外国英文网站强力推荐 (转)
  2. iOS-根据银行卡号判断银行名称
  3. 希望计算机专业同学都知道这些老师
  4. 4x root 红米_小米红米Note4X获取root权限教程
  5. oracle中varchar2类型的字段长度单位默认是按照byte来定义
  6. 基于SpringBoot的健身房管理系统
  7. 基于Hough变换的人眼虹膜定位
  8. Excel使用---excel2016___2维表转1维表(搬,侵删)
  9. MySQL存储引擎MyISAM和InnoDB的区别
  10. 修改MySQL的字符集为utf8mb4