题干
- 要从 A岸 出发到 B岸,A岸有 M 只羊、N 只狼和 1 个农夫,船每一趟可载 X 只动物。
- 有农夫看着、或则羊的数量大于狼,羊就不会被吃。
- 请返回任一躺数最少方案。
题解
题目可转化为:在一个有向无路长的图中,在不知道各个节点之间如何连接的基础上,找到两个节点之间的最短路径。
数据结构
public class Pack {
public int sheep; // 羊的数量
public int wolf; // 狼的数量
public int farmer;// 农夫的数量
}
public class Node {
public static HashSet<Node> s_finded; // 已经探索过的所有结点
public Pack landA; // A岸的情况
public Pack landB; // B岸的情况
public Node[] gotos; // 连接的结点
public Node from; // 来自结点
// 探索该节点能够前往的节点;返回是否探索到终点
public bool explore(int boatCarry);
// 将结点添加到 Node.s_finded 中
public void finded();
// 将结点添加到自己的 gotos 中;将结点的 from 设置为自己
public void markGoto(Node node);
}
算法
采用 bfs 广度优先算法来求最短路径,搭配剪枝来确保低计算复杂度:
- queue.Enqueue(起点)
while(!queue.isEmpty)
- node = queue.Dequeue()
node.explore(boatCarry) | boatCarry 是船的最大运载值
- this.find()
遍历所有支持的运载方案,对于运载方案指向的结点 goto:
- 羊+狼 超过最大运载 -> Continue
- 发现过 -> Continue
为终点
- goto.find()
- this.markGoto(goto)
- return true
不安全
- goto.find()
- Continue
- 安全 -> goto.find();this.markGoto(goto);goto入队
解题历程
一开始还不确定题目和图论相关,按照直接思路,构建了面向对象的相关方案,分别定义了类:岸、船、船渡。模拟对应的解题方案过程中,逐渐确认题型。
经过分析
- 两个状态:开始状态、目标状态
- 可剪枝:当状态下的某岸的 狼 大于等于 羊,该状态可剪
- 状态流转:船渡
题目建模
在一个有向无路长的图中,在不知道各个节点之间如何连接的基础上,找到两个节点之间的最短路径。
继续优化
- 从两个节点互相对外进行 BFS 搜索,猜测这样 时间复杂度会减半。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。