C# -算法:狼羊菜过河问题

7 篇文章 0 订阅
namespace 狼羊菜过河问题
{
    class Program
    {
        static string[] objects = new string[] { "人", "狼", "羊", "菜" };//对象数组
        static string[] start = new string[] { "1", "1", "1", "1", "0", "0", "0", "0" };//开始情况
        static string[] end = new string[] { "0", "0", "0", "0", "1", "1", "1", "1" };  //结束情况
        
        static int cnt = objects.Length;//几种对象

        static int count = 0;//解决方法数
        static void Main(string[] args)
        {
            var courseList = new List<RiverCrossCourse>();
            courseList.Add(new RiverCrossCourse() { info = "初始的情况", riverBank = string.Join(",", start).Split(',') });
            RiverCross(courseList, start);
            Console.ReadLine();
        }
        /// <summary>
        /// 来回过河
        /// </summary>
        /// <param name="courseList">直到上一步的过河过程集合信息</param>
        /// <param name="riverBank">上一步过河后河两岸情况</param>
        /// <param name="isCross">true是过河,false是返回,默认为true</param>
        static void RiverCross(List<RiverCrossCourse> courseList, string[] riverBank, bool isCross = true)
        {
            if (Enumerable.SequenceEqual(riverBank, end))//判断是否符合结束情况
            {
                WriteRiverCross(courseList);
                return;
            }
            for (int i = 0; i < cnt; i++)
            {
                if (isCross)
                {
                    if (riverBank[i] == "1")
                    {
                        BackOrForthAcrossRiver(courseList, riverBank, i);
                    }
                }
                else
                {
                    if (riverBank[i+cnt] == "1")
                    {
                        BackOrForthAcrossRiver(courseList, riverBank, i, isCross);
                    }
                }
            }
        }
        /// <summary>
        /// 循环添加来回过河过程
        /// </summary>
        /// <param name="courseList">直到上一步的过河过程集合信息</param>
        /// <param name="riverBank">上一步过河后河两岸情况</param>
        /// <param name="i">对象的编号,和对象数组objects有关</param>
        /// <param name="isCross">true是过河,false是返回,默认为true</param>
        static void BackOrForthAcrossRiver(List<RiverCrossCourse> courseList, string[] riverBank, int i, bool isCross = true)
        {
            var course = new RiverCrossCourse();
            string action = "返回";
            int num = cnt, num2 = 0;
            if (isCross)//如果过河,则是岸这边到那边
            {
                action = "过河"; num = 0; num2 = cnt;
            }
            if (i == 0)
                course.info = objects[0] + "独自" + action;
            else
                course.info = objects[0] + "带" + objects[i] + action;
            var newRiverBank = string.Join(",", riverBank).Split(',');//通过先将数组转字符串再转数组,来复制数据,而不影响原数据
            newRiverBank[num] = "0"; newRiverBank[num2] = "1";
            if (i != 0)
            {
                newRiverBank[i+num] = "0"; newRiverBank[i + num2] = "1";
            }
            if (CheckRepetition(courseList, newRiverBank)) return;//重复过河过程,抛弃这个过河方案
            if (!CheckPassMuster(newRiverBank)) return;//不符合要求,抛弃这个过河方案
            course.riverBank = newRiverBank;
            courseList.Add(course);
            RiverCross(courseList, newRiverBank, !isCross);//继续添加下一步的过河/返回操作
            courseList.Remove(course);//恢复原状,使得可以遍历多种情况//重点必须要加
        }
        /// <summary>
        /// 检测来回过河过程集合中是否有过河之后的河两岸情况和新的一次的过河之后的河两岸情况相同的
        /// </summary>
        /// <param name="courseList">来回过河过程集合</param>
        /// <param name="newRiverBank">新的一次的过河之后的河两岸情况</param>
        /// <returns>有,返回true,没有返回false</returns>
        private static bool CheckRepetition(List<RiverCrossCourse> courseList, string[] newRiverBank)
        {
            string str1 = string.Join(",", newRiverBank);
            foreach (var course in courseList)
            {
                string str2 = string.Join(",", course.riverBank);
                if (str1 == str2)
                {
                    return true;
                }
            }
            return false;
        }
        /// <summary>
        /// 检测新的一次的过河之后的河两岸情况符合不符合要求
        /// </summary>
        /// <param name="newRiverBank">新的一次的过河之后的河两岸情况</param>
        /// <returns>符合,返回true,不符合,返回false</returns>
        private static bool CheckPassMuster(string[] newRiverBank)
        {
            if (newRiverBank[0] == "0")//河岸一边没人
            {
                if (newRiverBank[1] == "1" && newRiverBank[2] == "1") return false;//没人有狼有羊,狼吃羊,不符合要求
                if (newRiverBank[2] == "1" && newRiverBank[3] == "1") return false;//没人有羊有菜,羊吃菜,不符合要求
            }
            else//河岸一边有人,则另一边必定没人
            {
                if (newRiverBank[1 + cnt] == "1" && newRiverBank[2 + cnt] == "1") return false;//没人有狼有羊,狼吃羊,不符合要求
                if (newRiverBank[2 + cnt] == "1" && newRiverBank[3 + cnt] == "1") return false;//没人有羊有菜,羊吃菜,不符合要求
            }
            return true;
        }
        /// <summary>
        /// 写出过河过程信息
        /// </summary>
        /// <param name="courseList">过河过程集合</param>
        private static void WriteRiverCross(List<RiverCrossCourse> courseList)
        {
            Console.WriteLine("第{0}种解决方案:\n", ++count);
            foreach (var course in courseList)
            {
                Console.WriteLine(course.info + ":  河两岸情况: " + string.Join(",", course.riverBank));
            }
            Console.WriteLine();
        }
    }
    /// <summary>
    /// 类-过河过程
    /// </summary>
    class RiverCrossCourse
    {
        /// <summary>
        /// 过河操作信息
        /// </summary>
        public string info;
        /// <summary>
        /// 过河后两岸情况
        /// </summary>
        public string[] riverBank;
    }
}

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值