算法谜题1,狼羊菜过河

问题描述

农夫需要把狼、羊、菜和自己运到河对岸去,只有农夫能够划船,而且船比较小,除农夫之外每次只能运一种东西,还有一个棘手问题,就是如果没有农夫看着,羊会偷吃菜,狼会吃羊。请考虑一种方法,让农夫能够安全地安排这些东西和他自己过河。

分析

问题很简单,但如何用计算机求解呢。

农夫渡河从本质上是一种状态的改变。

有农夫、狼、羊、菜四个个体,任何时刻每个个体的状态只有一种,每个个体有两种状态(没有过河、已经过河)。

依次用4位分别代表农夫、狼、羊、菜,0表示未过河,1表示已过河。则起始状态为0000,目标状态为1111。

共有8种过河动作(状态转换运算)

  • 农夫单独过河
  • 农夫带狼过河
  • 农夫带羊过河
  • 农夫带菜过河
  • 农夫单独返回
  • 农夫带狼返回
  • 农夫带羊返回
  • 农夫带菜返回

优先级:
农夫过河时,优先带货物;回返时优先不带货物。

有限种状态:

可能有16(2^4)种状态,但因为狼吃羊,羊吃菜的限制,部分状态是无法成立的。

实现

状态空间树(回溯法)

是以0000为根的一颗状态树,当某个叶子节点是状态1111,则表示从根到这个叶子节点之间的状态序列是本问题的一个解,需要避免出现重复状态导致死循环。
方法1: 每个状态有8种可选动作,转换为8个新状态,但在特定状态下某些动作是无效的。

定义8种状态转换运算,对当前节点遍历执行这8种运算,找到所有子节点

方法2: 依据当前状态,判别它所有可选的动作(最多4种)。

class Program
{
    static void Main(string[] args)
    {
        var original = new State();

        var path = new List<State>();
        path.Add(original);
        int count = 0;
        Search(path, ref count);

        Console.ReadKey();
    }

    private static void Search(List<State> path, ref int count)
    {
        var cur = path[path.Count - 1];

        if (cur.Man && cur.Wolf && cur.Vegetable && cur.Sheep)
        {
            count+&
  • 0
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值