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;
}
}