C#实现倒油算法
今天把上次在同学群里提到的算法用C#实现了,居然整了几个小时。
原题如下:12(a桶 满的 有12斤油)斤桶里 取出6斤油 有 另外有8斤(b桶)和5斤(c桶)两个空桶 让程序输出取出这6斤油的步骤
现在实现的算法可以配参数(定义有几个桶,初始有多少油,要得到多少油,都可以配),并且找出任意(多条线路或者找不到)满足条件的倒油线路图:
运行效果:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ConsoleApplication2
{
class Program
{
static void Main(string[] args)
{
//在此自定义相关初始信息
Oil.初始油量 = "12,0,0";
Oil.桶的容量 = "12,8,5";
Oil.需求油量 = "6";
Oil oil = new Oil();
Status SuperStatus = oil.GetStartState();
oil.status.Add(SuperStatus);
oil.执行(SuperStatus);
if (oil.Endstatus.Count == 0)
{
Console.WriteLine("无法倒出指定质量大小的油。");
}
else
{
Console.WriteLine("共找到" + oil.Endstatus.Count.ToString()+"条倒油线路:");
}
for (int i = 0; i < oil.Endstatus.Count; i++)
{
Console.WriteLine(oil.翻译路线(oil.Endstatus[i]));
}
}
}
class Oil
{
public static string 桶的容量;
public static string 初始油量;
public static string 需求油量;
//自动记录桶的总数
int count;
public Oil()
{
count = 桶的容量.Split(',').Count();
capacity = new int[count];
for (int i=0;i<count;i++)
{
capacity[i] = Convert.ToInt32(桶的容量.Split(',')[i]);
}
}
public int[] capacity; //new int[] { 12, 8, 5 };
public List<Status> status = new List<Status>();
public List<Status> Endstatus = new List<Status>();
Status 倒油(Status state, int a, int b)
{
//排除不可倒的情况
if (state.OilState[a] == 0) return null;
if (state.OilState[b] == capacity[b]) return null;
//倒油操作
//先定义成功倒油后的新状态
Status newStatus = new Status();
newStatus.OilState = new int[count];
state.OilState.CopyTo(newStatus.OilState, 0);
newStatus.Father = state;
if (state.OilState[a] > capacity[b] - state.OilState[b])
{
newStatus.OilState[a] -= capacity[b] - state.OilState[b];
newStatus.OilState[b] = capacity[b];
}
else
{
newStatus.OilState[a] = 0;
newStatus.OilState[b] += state.OilState[a];
}
//判断倒油后的新状态是否在状态列表中存在
bool IsExist = false;
foreach (var s in status)
{
bool mark = true;
for (int i = 0; i < newStatus.OilState.Count(); i++)
{
if (newStatus.OilState[i] != s.OilState[i]) mark = false;
}
if (mark)
{
IsExist = true;
break;
}
}
if (IsExist)
{
return null;
}
else
{
status.Add(newStatus);
return newStatus;
}
}
public void 执行(Status SuperStatus)
{
//如果找到一条路线
if (SuperStatus.OilState.Contains(Convert.ToInt32(需求油量)))
{
Endstatus.Add(SuperStatus);
ArrangeStatus();
执行(GetStartState());
return;
}
for (int a = 0; a < count; a++)
{
for (int b = 0; b < count; b++)
{
if (b != a)
{
Status newStatus = 倒油(SuperStatus, a, b);
if (newStatus != null)
{
执行(newStatus);
}
}
}
}
}
public string 翻译路线(Status endState)
{
string theWay = string.Empty;
Status s = endState;
while (s != null)
{
string wayNode = string.Empty;
foreach (var a in s.OilState)
{
wayNode += a.ToString() + " ";
}
if (theWay == string.Empty) theWay += wayNode;
else theWay = wayNode.Trim() + "→" + theWay;
s = s.Father;
}
return theWay;
}
/// <summary>
/// 整理状态表,为寻求新路线做准备
/// </summary>
public void ArrangeStatus()
{
status.Clear();
for (int i = 0; i < Endstatus.Count; i++)
{
Status s = Endstatus[i];
while (s != null)
{
status.Add(s);
s = s.Father;
}
}
}
/// <summary>
/// 获取开始状态
/// </summary>
/// <returns></returns>
public Status GetStartState()
{
Status status = new Status();
status.Father = null;
status.OilState = new int[count];
for (int i = 0; i < count; i++)
{
status.OilState[i] = Convert.ToInt32(初始油量.Split(',')[i]);
}
return status;
}
}
/// <summary>
/// 记录各桶当前所装油量的状态信息
/// </summary>
class Status
{
public int[] OilState;
public Status Father;
}
}