namespace 三桶等分水问题
{
class Program
{
/// <summary>
/// 初始桶存水信息
/// </summary>
static int[] start = new int[] { 8, 0, 0 };
/// <summary>
/// 所有桶最大水容量信息
/// </summary>
static int[] MaxVolume = new int[] { 8, 5, 3 };
/// <summary>
/// 结束桶存水信息
/// </summary>
static int[] end = new int[] { 4, 4, 0 };
/// <summary>
/// 桶数量
/// </summary>
static int len;
/// <summary>
/// 方法数
/// </summary>
static int number = 0;
static void Main(string[] args)
{
len = start.Length;
List<Course> result = new List<Course>();
result.Add(new Course(start));
GetDumpCourse(result);
Console.ReadLine();
}
/// <summary>
/// 根据所有桶的现存水的数组信息初始化桶数组信息
/// </summary>
/// <param name="NowVolume">所有桶的现存水的数组信息</param>
/// <returns></returns>
private static Bucket[] InitBucketList(int[] NowVolume)
{
var list = new Bucket[len];
for (int i = 0; i < len; i++)
{
list[i] = new Bucket(NowVolume[i], MaxVolume[i]);
}
return list;
}
/// <summary>
/// 获取倒水数组信息
/// </summary>
/// <param name="result">上一步的倒水数组信息</param>
private static void GetDumpCourse(List<Course> result)
{
int cut = result.Count;
var num = result[cut - 1].bucketExisting;//倒水数组的最后的桶存水数组信息
var list = InitBucketList(num);
int cnt = len * len;
for (int i = 0; i < cnt; i++)
{
int r = i / len;//将二重循环降为一重循环,r为横坐标
int c = i % len;//将二重循环降为一重循环,c为纵坐标
if (Enumerable.SequenceEqual(num, end))//判断是否已经符合结束桶存水信息
{
WriteDumpCourse(result);
return;
}
if (CheckBucket(r, c, list))
{
//尝试倒水
int maxGive = list[r].existing;
int maxGain = list[c].volume - list[c].existing;
int min = maxGive;
if (min >= maxGain)
{
min = maxGain;
}
list[c].existing += min;
list[r].existing -= min;
//倒水过程加入数组
result.Add(new Course(min, r + 1, c + 1));
if (CheckDump(result, list))
GetDumpCourse(result);
//恢复原状态
list[c].existing -= min;
list[r].existing += min;
result.RemoveAt(cut);
}
}
}
/// <summary>
/// 输出倒水过程信息
/// </summary>
/// <param name="courseList">倒水过程数组</param>
private static void WriteDumpCourse(List<Course> courseList)
{
Console.WriteLine("第{0}种方法:一共有{1}步步骤:\n", ++number, courseList.Count);
foreach (Course c in courseList)
{
Console.WriteLine("从 {0} 桶倒 {1} 水入 {2} 桶,所有桶的水量是:{3}", c.fromNumber, c.dumpVolume, c.toNumber, string.Join(" ", c.bucketExisting));
}
Console.WriteLine();
}
/// <summary>
/// 判断倒水过程(若原过程数组中有与此次倒水之后的桶数组信息相同的,则判断倒水过程数组中有循环操作,舍弃,没有则判断倒水过程符合,加入倒水过程数组)
/// </summary>
/// <param name="courseList">过程数组</param>
/// <param name="list">此次倒水之后的桶数组信息</param>
/// <returns></returns>
private static bool CheckDump(List<Course> courseList, Bucket[] list)
{
int[] num = new int[len];
for (int j = 0; j < len; j++)
{
num[j] = list[j].existing;
}
int cnt = courseList.Count;
for (int i = 0; i < cnt - 1; i++)
{
if (Enumerable.SequenceEqual(courseList[i].bucketExisting, num))
return false;
}
courseList[cnt - 1].bucketExisting = num;
return true;
}
/// <summary>
/// 判断是否可以倒水
/// </summary>
/// <param name="r">水来源桶</param>
/// <param name="c">水倒入桶</param>
/// <param name="list">桶数组</param>
/// <returns></returns>
private static bool CheckBucket(int r, int c, Bucket[] list)
{
if (r == c) return false; //水来源桶与水倒入桶为同一个桶,不能倒水
if (list[r].existing == 0) return false;//水来源桶没水,不能倒水
if (list[c].existing == list[c].volume) return false;//水倒入桶已满,不能倒水
return true;
}
/// <summary>
/// 类-桶
/// </summary>
class Bucket
{
/// <summary>
/// 最大容量
/// </summary>
public int volume;
/// <summary>
/// 现存水量
/// </summary>
public int existing;
public Bucket(int exist, int maxV)
{
volume = maxV;
existing = exist;
}
}
/// <summary>
/// 类-倒水过程
/// </summary>
class Course
{
/// <summary>
/// 倒水量
/// </summary>
public int dumpVolume;
/// <summary>
/// 水来源桶号
/// </summary>
public int fromNumber;
/// <summary>
/// 水倒入桶号
/// </summary>
public int toNumber;
/// <summary>
/// 所有桶现存水数组信息
/// </summary>
public int[] bucketExisting;
public Course(int dumpV, int from, int to)
{
// TODO: Complete member initialization
this.dumpVolume = dumpV;
this.fromNumber = from;
this.toNumber = to;
}
public Course(int[] start)
{
dumpVolume = start[0];
fromNumber = 0;
toNumber = 1;
bucketExisting = new int[len];
for (int i = 0; i < len; i++)
{
bucketExisting[i] = start[i];
}
}
}
}
}