之前好像在博客园看到这样的题目:
1.有3个容器,各是20升,13升,7升, 形状不同也不透明。一开始20升的容器里面装了20升水,反正倒来倒去最后要让20升和13升容器各装了10升水
2. 2个外形不同的瓶子,各装800毫升水,另外还有1个300毫升的杯子
现在有4个人,不限制喝的次数,想办法让每个人都正好喝到400毫升水
第一第二道题目,口头说明解法就行了
第三个题,就是从第一第二题里面随便选择一个,使用编程来求解
于是乎..觉得有趣.便做了起来...花了一个下午的时间..终于做出来了:
首先建了一个水杯类: //以下程序只是基于可运行..至于代码的可看性和性能,暂时还没做优化
public class Cut
{
private int _maxValue;//杯子的最大值
public int MaxValue
{
get
{
return _maxValue;
}
}
private int _currentValue;//杯子当前值
public int CurrentValue
{
get
{
return _currentValue;
}
set
{
_currentValue = value;
}
}
public Cut(int maxValue,int currentValue)
{
_maxValue = maxValue;
_currentValue = currentValue;
}
}
然后在控制台程序环境下:
class Program
{
private static List<int[]> valueList = new List<int[]>();//用于记录正确的步骤
private static int[] values = new int[3];//当前的步骤
private static Cut c7 = new Cut(7, 0);
private static Cut c13 = new Cut(13, 0);
private static Cut c20 = new Cut(20, 20);
static void Main(string[] args)
{
valueList.Clear();
ChangeCut(ref c7, ref c13, ref c20);
}
static bool GetDirection(int[] currentValues)//true表示可以继续下一次[节点不存在],false则反之[表示节点存在]
{
if (valueList.Count == 0)//第一次时.不存在重复节点,返回真
{
return true;
}
int count = 0;
for (int i = 0; i < valueList.Count; i++)
{
for (int j = 0; j < 3; j++)
{
if (valueList[i][j] == currentValues[j])//只要发现不相等,转入下一个
{
count++;
if (count == 3)
{
return false;
}
}
else
{
count = 0;
break;
}
}
}
return true;
}
static void ChangeCut(ref Cut c1, ref Cut c2, ref Cut c3)
{
Cut cutA = c2;//第一次交换的值
Cut cutB = c3;;//第一次交换的值
while (true)
{
if (!ChangeTwoCut(ref cutA, ref cutB))//交换两个杯的值
{
valueList.RemoveAt(valueList.Count - 1);//交换失败时.删除最后一个节点
c7.CurrentValue = valueList[valueList.Count - 1][0];//退回上一节点的值
c13.CurrentValue = valueList[valueList.Count - 1][1];//退回上一节点的值
c20.CurrentValue = valueList[valueList.Count - 1][2];//退回上一节点的值
}
RadomCut(ref c1, ref c2, ref c3, out cutA, out cutB);//随机取两个杯交换
}
}
static void RadomCut(ref Cut c1, ref Cut c2, ref Cut c3, out Cut c11, out Cut c12)//随机产生两个杯
{
Random rd = new Random();
int result = rd.Next(3);
if (result == 0)
{
c11 = c1;
}
else if (result == 1)
{
c11 = c2;
}
else
{
c11 = c3;
}
int result2 = rd.Next(3);
while (result2 == result)//用于产生不和上面重复的值
{
result2 = rd.Next(2);
}
if (result2 == 0)
{
c12 = c1;
}
else if (result2 == 1)
{
c12 = c2;
}
else
{
c12 = c3;
}
}
static bool ChangeTwoCut(ref Cut c1, ref Cut c2)
{
bool result = false;
int valueA;
int valueB;
int tempA = c1.CurrentValue;
int tempB = c2.CurrentValue;
//默认先走左边
GetChangedValue(c1, c2, out valueA, out valueB, true);//两个杯交换后的值
c1.CurrentValue = valueA;
c2.CurrentValue = valueB;
if (GetDirection(new int[] { c7.CurrentValue, c13.CurrentValue, c20.CurrentValue }))
{
result = true;
}
else //走右边
{
GetChangedValue(c1, c2, out valueA, out valueB, false);
c1.CurrentValue = valueA;
c2.CurrentValue = valueB;
if (GetDirection(new int[] { c7.CurrentValue, c13.CurrentValue, c20.CurrentValue }))
{
result = true;
}
}
if (result)
{
GetResult();
}
else //失败,还原值
{
c1.CurrentValue = tempA;
c2.CurrentValue = tempB;
}
return result;
}
static void GetChangedValue(Cut c1, Cut c2, out int valueA, out int valueB, bool AtoB)//两种情况,一种A的值给B,一种B的值给A
{
int maxValue = c1.CurrentValue + c2.CurrentValue;
//边界测定
if (c1.CurrentValue == 0)
{
valueA = c2.CurrentValue > c1.MaxValue ? c1.MaxValue : maxValue;
valueB = maxValue - valueA;
}
else if (c1.CurrentValue == c1.MaxValue)
{
int need = c2.MaxValue - c2.CurrentValue;
if (c1.CurrentValue >= need)
{
valueA = c1.CurrentValue - need;
valueB = c2.CurrentValue + need;
}
else
{
valueA = 0;
valueB = maxValue;
}
}
else if (c2.CurrentValue == 0)
{
valueB = c1.CurrentValue > c2.MaxValue ? c2.MaxValue : maxValue;
valueA = maxValue - valueB;
}
else if (c2.CurrentValue == c2.MaxValue)
{
int need = c1.MaxValue - c1.CurrentValue;
if (c2.CurrentValue > need)
{
valueA = c1.CurrentValue + need;
valueB = c2.CurrentValue - need;
}
else
{
valueA = maxValue;
valueB = 0;
}
}
else //非边界值时
{
if (AtoB)//A的值给B时
{
valueB = maxValue > c2.MaxValue ? c2.MaxValue : maxValue;
valueA = maxValue - valueB;
}
else//B的值给A时
{
valueA = maxValue > c1.MaxValue ? c1.MaxValue : maxValue;
valueB = maxValue - valueA;
}
}
}
static void GetResult() //添加正确步骤或显示结果
{
if (c20.CurrentValue == 10 || c13.CurrentValue == 10)
{
int[] newValue = new int[3] { c7.CurrentValue, c13.CurrentValue, c20.CurrentValue };
valueList.Add(newValue);
Console.WriteLine("结果已出如下:");
for (int i = 0; i < valueList.Count; i++)
{
Console.WriteLine("第" + i.ToString() + "步: " + valueList[i][0].ToString() + ":" + valueList[i][1].ToString() + ":" + valueList[i][2].ToString());
}
Console.ReadLine();
}
else
{
int[] newValue = new int[3] { c7.CurrentValue, c13.CurrentValue, c20.CurrentValue };
valueList.Add(newValue);
Console.WriteLine(newValue[0].ToString() + ":" + newValue[1].ToString() + ":" + newValue[2].ToString());
}
}
}