62,046
社区成员
发帖
与我相关
我的任务
分享
StringBuilder sb = new StringBuilder();
Action<int, int, bool, int> pullWater = null;
pullWater = (a, b, isFromSmallToBig, count) =>
{
if (b == 4 || count > 20) //最多试20步
return;
if (isFromSmallToBig)
{
if (b == 5) //如果5升的杯子满了
{
sb.AppendLine("empty big cup;");
pullWater(a, 0, true, count++);
}
else if (a == 0) //3升的杯子是空的
{
sb.AppendLine("fill up small cup;");
pullWater(3, b, true, count++);
}
else if (a + b <= 5) //倒水不会溢出
{
sb.AppendLine("pull " + a.ToString() + " l water to big cup and "
+ "big cup now has " + (a + b).ToString() + " l water;");
pullWater(0, a + b, true, count++);
}
else
{
sb.AppendLine("small cup has " + a.ToString() +
" l water and pull " + (5 - b).ToString() + " l water to big cup.");//{0}升水其中{1}升倒入5升杯子。", a, 5 - b);
pullWater(a + b - 5, 5, true, count++);
}
}
else
{
if (a == 3) //如果3升的杯子满了
{
sb.AppendLine("empty small cup;");
pullWater(0, b, false, count++);
}
else if (b == 0) //5升的杯子是空的
{
sb.AppendLine("fill up big cup;");
pullWater(a, 5, false, count++);
}
else if (a + b <= 3) //倒水不会溢出
{
sb.AppendLine("pull " + b.ToString() + " l water to small cup and "
+ "small cup now has " + (a + b).ToString() + " l water;");
pullWater(a + b, 0, false, count++);
}
else
{
sb.AppendLine("big cup has " + b.ToString() +
" l water and pull " + (3 - a).ToString() + " l water to small cup.");//{0}升水其中{1}升倒入5升杯子。", a, 5 - b);
pullWater(3, a + b - 3, false, count++);
}
}
};
pullWater(0, 0, true, 0);
sb.AppendLine("------------------");
pullWater(0, 0, false, 0);
public class Cups
{
public int CupA { get; set; }
public int CupB { get; set; }
}
Cups cups = new Cups();
bool result = false;
SortedList<string, string> steps = new SortedList<string, string>();//存储操作步骤
List<string> quickest = new List<string>();
StringBuilder sb = new StringBuilder();
for (int i = 0; i < 16; i++)
{//只计算最多15步,所以这里初始成16步,相当于“无限大”
sb.Append("1");
}
sb.Append("0");
quickest.Add(sb.ToString());
sb.Remove(98, 1);
sb.Append("1");
quickest.Add(sb.ToString());
sb.Length = 0;
for (int i = 0; i < 32768; i++)
{//32768 = 2^15,也就是说最多计算15步
//转化成2进制,每1位代表一个操作步骤,0表示从小杯往大杯倒水
//1表示从大杯往小杯倒水。这里i取0到2^15,穷尽15步内的所有可能操作
string stepString = Convert.ToString(i, 2);
//注意对于不足15位的数,前面必须补0,不然类似0010,0000的操作步骤就被忽略了
for (int j = 0; j < 15 - stepString.Length; j++)
{
sb.Append("0");
}
sb.Append(stepString);
stepString = sb.ToString();
sb.Length = 0;
bool isContinue = false;
foreach (string key in steps.Keys)
{//检查是否与已有结果重复,但这其实是不完善的,原因上面已经解释了
if (stepString.StartsWith(key))
{
isContinue = true;
break;
}
}
if (isContinue)
{
continue;
}
cups.CupA = 3;//复位到初始状态,小杯3升水,大杯5升
cups.CupB = 5;
StringBuilder tmpSteps = new StringBuilder();//复位临时的操作步骤
for (int j = 0; j < stepString.Length; j++)
{//
string step = "";
result = pullWater3(stepString[j], cups, out step);//倒水操作
tmpSteps.AppendLine(step);
if (result)
{//若得到一个解
//获得当前操作步骤的2进制字符串表示
string substeps = stepString.Substring(0, j);
if (checkQuickest3(quickest, substeps))
{//如果属于最快的方法之一,加入到最终的输出结果集
steps.Add(substeps, tmpSteps.ToString());
}
break;//没必要走完15步,继续找下一种方法
}
}
}
if (steps.Count > 0)
{//如有解,输出结果
outputSteps3(steps, quickest);
}
}
private void outputSteps3(SortedList<string, string> steps, List<string> quickest)
{//输出结果
StringBuilder sb = new StringBuilder();
for (int i = 0; i < 2; i++)
{//找到最快的2种方法
if (steps.ContainsKey(quickest[i]))
{
sb.Append(steps[quickest[i]]);
sb.AppendLine("----------------------");
}
}
txtResult.Text = sb.ToString();
}
private bool checkQuickest3(List<string> quickest, string candidateSteps)
{//检查是否是最快的方法之一
bool isQuickest = false;
for (int i = 0; i < 2; i++)
{//只找最快的前2种,排除重复
if (candidateSteps.Length < quickest[i].Length
|| (candidateSteps.Length == quickest[i].Length
&& candidateSteps != quickest[i])
)
{
quickest.Insert(i, candidateSteps);
isQuickest = true;
break;
}
}
return isQuickest;
}
private bool pullWater3(char type, Cups cups, out string step)
{//倒水操作,类似sp1234,不过考虑了从小杯倒大杯和从大杯倒小杯两种情况
step = "";
StringBuilder sb = new StringBuilder();
int tofill = 0;
if (cups.CupB == 4)
{
return true;
}
if (type == '0')
{//从小杯到大杯
if (cups.CupB == 5)
{//大杯满
sb.Append(" 倒空大杯;");
cups.CupB = 0;
}
tofill = 5 - cups.CupB;
if (cups.CupA == 0)
{//小杯空
sb.Append(" 加满小杯;");
cups.CupA = 3;
}
if (cups.CupA <= 5 - cups.CupB)
{
tofill = cups.CupA;
}
sb.Append(" 从小杯倒 " + tofill.ToString() + " 升水倒大杯;");
cups.CupA -= tofill;
cups.CupB += tofill;
}
else
{//大杯到小杯
if (cups.CupA == 3)
{
sb.Append(" 倒空小杯;");
cups.CupA = 0;
}
tofill = 3 - cups.CupA;
if (cups.CupB == 0)
{
sb.Append(" 加满大杯;");
cups.CupB = 5;
}
if (cups.CupB <= 3 - cups.CupA)
{
tofill = cups.CupB;
}
sb.Append(" 从大杯倒 " + tofill.ToString() + " 升水到小杯;");
cups.CupA += tofill;
cups.CupB -= tofill;
}
step = sb.ToString();
if (cups.CupB == 4)
{
return true;
}
else
{
return false;
}
}
Action<int, int> 倒水 = null;
倒水 = (a, b) =>
{
begin:
if (b == 4)
return;
else if (b == 5) //如果5升的杯子满了
{
Console.Write("到空5升杯子。");
b = 0;
goto begin;
}
else if (a == 0) //3升的杯子是空的
{
Console.Write("倒满3升杯子。");
a = 3;
goto begin;
}
else if (a + b <= 5) //倒水不会溢出
{
Console.Write("{0}升水倒入杯子成{1}升。", a, a + b);
b = a + b;
a = 0;
goto begin;
}
else
{
Console.Write("{0}升水其中{1}升倒入5升杯子。", a, 5 - b);
a = a + b - 5;
b = 5;
goto begin;
}
};
using System;
using System.Collections.Generic;
using System.Linq;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
Func<int, long> fib = null;
fib = n =>
{
if (n <= 2)
return 1;
else
return fib(n - 1) + fib(n - 2);
};
Console.WriteLine("第一题:{0}", fib(30));
(from a in 真话()
from b in 真话()
from c in 真话()
where a != b && b != c && c != (a && b)
select new { A = a, B = b, C = c })
.ToList()
.ForEach(query =>
{
Console.WriteLine("第二题(说真话):A={0} B={1} C={2}", query.A, query.B, query.C);
});
Action<int, int> 倒水 = null;
倒水 = (a, b) =>
{
if (b == 4)
return;
else if (b == 5) //如果5升的杯子满了
{
Console.Write("到空5升杯子。");
倒水(a, 0);
}
else if (a == 0) //3升的杯子是空的
{
Console.Write("倒满3升杯子。");
倒水(3, b);
}
else if (a + b <= 5) //倒水不会溢出
{
Console.Write("{0}升水倒入杯子成{1}升。", a, a + b);
倒水(0, a + b);
}
else
{
Console.Write("{0}升水其中{1}升倒入5升杯子。", a, 5 - b);
倒水(a + b - 5, 5);
}
};
倒水(0, 0);
Console.ReadKey();
}
static IEnumerable<bool> 真话()
{
yield return true;
yield return false;
}
}
}
private bool pullWater(bool isFromSmallToBig, Cups cups, List<string> steps)
{//模拟倒水操作
int tofill = 0;
if (cups.CupB == 4)
{//若操作前大杯已有4升水,直接返回
return true;
}
if (isFromSmallToBig)
{//小杯倒大杯
if (cups.CupB == 5)
{//若大杯满,先倒空
cups.CupB = 0;
}
tofill = 5 - cups.CupB;//可向大杯里倒的水量
if (cups.CupA == 0)
{//若小杯空,先装满后再倒
cups.CupA = 3;
}
if (cups.CupA <= 5 - cups.CupB)
{//若小杯水倒不满大杯
tofill = cups.CupA;
}
steps.Add("true:" + tofill.ToString());//记录操作步骤
cups.CupA -= tofill;
cups.CupB += tofill;
}
else
{//大杯倒小杯
if (cups.CupA == 3)
{//若小杯满,先倒空
cups.CupA = 0;
}
tofill = 3 - cups.CupA;//可往小杯倒的水量
if (cups.CupB == 0)
{//若大杯空,先倒满
cups.CupB = 5;
}
if (cups.CupB <= 3 - cups.CupA)
{
tofill = cups.CupB;
}
steps.Add("false:" + tofill.ToString());
cups.CupA += tofill;
cups.CupB -= tofill;
}
if (cups.CupB == 4)
{//若大杯有4升水
return true;
}
else
{
return false;
}
}