本周bfs专题训练
T1 Maze
题目描述
东东有一张地图,想通过地图找到妹纸。地图显示,0表示可以走,1表示不可以走,左上角是入口,右下角是妹纸,这两个位置保证为0。既然已经知道了地图,那么东东找到妹纸就不难了,请你编一个程序,写出东东找到妹纸的最短路线。
题目分析
起点终点已经确定,地图大小也已经确定,因此无需考虑数据,直接从起点bfs即可。
由于要求输出路径而不是步数,因此每次转移时需要记录上一个状态,在到达终点后直接倒序输出就可以了。
可以用指针或者数组模拟指针来记录历史状态。
一个位置能不能走到的前提有两个:1. 没有墙 2. 之前没有走过。
四个方向行走可以用经典的方法:开两个数组,分别代表向四个方向移动的坐标变化。
代码
1 | int map[10][10]; |
T2 Pour Water
题目描述
经典的倒水问题,有两个容量分别为A,B升的杯子,每个杯子支持三种操作:
- 把杯子倒满
- 把杯子倒空
- 把这个杯子里的水倒到另一个杯子
问能不能倒出C升的水
保证A,B互质。
输出操作次数最少的操作流程(不唯一)。
题目分析
- xxx最少balabalabala,用bfs比较多(当然本期主题是bfs
康复训练练习) - 一个杯子支持三个操作,那么两个杯子支持六种操作。也就是对于某个时刻的两个杯子,下一个时刻可能存在的状态有六种,其实也就是bfs时最多产生六个分支。
- 用面向对象思想,给每个bottle写三个方法:$ pourIn(),pourOut(),pourTo(bottle&) $ 分别代表三种操作。这样写出来的代码比较清晰明了。(虽然看上去很长2333)
- 输出操作流程。和上一题同样的思想,用指针记录上一个状态,最后倒序输出。不太一样的是还要多记录一个opt:从上一个状态到当前状态的操作(倒满/倒空/倒到另一个杯子)
- 同时也要开一个数组记录当前状态是否达到过,如果到过就不用重复入队了。
代码
1 | struct bottle{ |
反思
可以用函数数组来改写一下:
1 | void (*p[6])(bottle& a,bottle& b) //定义 |
不过这就得定义六个函数,代码量不一定能减少多少,只是提供一种思路。