一个简单的青蛙算法~~
一个哥们给了道有意思的题,我贴出来与大家分享,还有我简单解。
★问题描述:
在一条水平的瓷砖道路上,有一只迷路的小青蛙。这只青蛙可以沿着水平道
路向前或者向后,行走或者跳跃。瓷砖有两种颜色,分别为黑色和白色,青蛙所
在的位置被标记为空格。青蛙可以走到相邻(向前或者向后)的瓷砖上。
当青蛙沿着瓷砖行走时,青蛙原先所在的位置状态变为青蛙走到的位置状
态,青蛙走到的位置被标记为空格。例如,在下图中,在青蛙的前面有三块瓷砖,
在青蛙的后面有二块瓷砖。我们可以使用“BWFBBW”来表示当前的状态,其中F
表示空格(即青蛙所在的位置),B 表示瓷砖是黑色的,W 表示瓷砖是白色的。如
果青蛙向前行走,状态变为“BWBFBW”。同样的,如果青蛙向后行走,状态变为
“BFWBBW”。即青蛙的位置与相邻的瓷砖相交换。
青蛙还可以在瓷砖上跳跃,青蛙可以隔着一块瓷砖跳到下一块瓷砖上,同样
的,青蛙隔着的瓷砖状态将变化,即从W 变为B,从B 变为W,青蛙原先所在的
位置状态变为青蛙跳跃到的位置状态。例如,在下图中,当青蛙向前跳跃时,状
态变为“BWWBFW”,当青蛙向前跳跃时,状态变为“FWWBBW”。
现在要求在任意两块黑色瓷砖之间都不能有白色瓷砖,请你计算出青蛙所需
要移动(行走或者跳跃)的最小步数。
给定瓷砖的状态,请你计算出青蛙所需要移动(行走或者跳跃)的最小步数。
★数据输入:
输入有多组数据,每组输入数据的第一行为一个整数T(1≤T≤10),表示输
入数据的组数,以下T行,每行有一个字符串S,S的长度不大于100且不为空,S
只包含字符“BWF”并且只有一个字符F,表示瓷砖的状态。
★结果输出:
对于每组输入数据输出一行一个整数,表示青蛙所需要移动(行走或者跳跃)
的最小步数,如果需要超过10 步才能完成,请输出“-1”。
输入示例
WWBBFBW
WBFBWBBWBWBWBWB
根据这个算出步子就可以了.
我的解:
{
static void Main(string[] args)
{
///首先是获得输入序列
while (true)
{
int Cur, CountL = 0, CountR = 0;
Console.WriteLine("请输入序列。");
string StrRoad = Console.ReadLine();
string ResvStrRoad = Reverse(StrRoad);
Console.WriteLine("已经获得输入序列:" + StrRoad);
///之后,根据题意,先想到第一个算法:穷举。因为跳肯定比走快吧,所以每次轮到青蛙走的时候,先让它跳,如果跳之后出现了黑白+黑的情况,则换走,如果走再出错。
///就没办法了。每步都这样走,就会得到最优的路线。
Regex reg = new Regex("B[^B]*W+[^B]*B");
if (reg.IsMatch(StrRoad))
{
Console.WriteLine("您输入的序列有误,不允许两个黑之间出现白色。");
continue;
}
Cur = StrRoad.IndexOf('F');
if (Cur == -1)
{
Console.WriteLine("您输入的序列不包含青蛙F,请重新输入。");
continue;
}
Console.WriteLine("首先开始正序尝试");
do
{
Console.WriteLine("当前青蛙位置:" + (Cur + 1));
Swap(ref StrRoad, Cur, Cur + 2);
if (reg.IsMatch(StrRoad) || Cur + 2 > StrRoad.Length)
{
Swap(ref StrRoad, Cur + 2, Cur);
Swap(ref StrRoad, Cur, Cur + 1);
if (reg.IsMatch(StrRoad))
{
Console.WriteLine("正序尝试失败。");
CountL = -1;
break;
}
else
{
Cur++;
CountL++;
Console.WriteLine("青蛙往前走了一步,进入了:" + (Cur + 1));
}
}
else
{
Cur += 2;
CountL++;
Console.WriteLine("青蛙往前跳了一步,进入了:" + (Cur + 1));
}
}
while (Cur < StrRoad.Length);
if (CountL != -1)
{
Console.WriteLine("正序尝试成功,步数为" + CountL.ToString());
}
Console.WriteLine("下面考虑倒序。");
StrRoad = ResvStrRoad;
Cur = StrRoad.IndexOf('F');
do
{
Console.WriteLine("当前青蛙位置:" + (StrRoad.Length - Cur).ToString());
Swap(ref StrRoad, Cur, Cur + 2);
if (reg.IsMatch(StrRoad) || Cur + 2 > StrRoad.Length)
{
Swap(ref StrRoad, Cur + 2, Cur);
Swap(ref StrRoad, Cur, Cur + 1);
if (reg.IsMatch(StrRoad))
{
Console.WriteLine("倒序尝试失败。");
CountR = -1;
break;
}
else
{
Cur++;
CountR++;
Console.WriteLine("青蛙往前走了一步,进入了:" + (StrRoad.Length - Cur).ToString());
}
}
else
{
Cur += 2;
CountR++;
Console.WriteLine("青蛙往前跳了一步,进入了:" + (StrRoad.Length - Cur).ToString());
}
}
while (Cur < StrRoad.Length);
if (CountR == -1)
{
Console.WriteLine("最终青蛙无法离开。");
}
else
{
Console.WriteLine("倒序尝试成功,步数为:" + CountR.ToString());
Console.WriteLine("综上考虑,两种序列,最优解为:" + (CountL < CountR ? CountL : CountR).ToString());
}
}
}
static void Swap(ref string s, int pos, int newpos)
{
if (pos >= s.Length || newpos >= s.Length)
return;
StringBuilder sb = new StringBuilder(s);
char c = sb[pos];
sb[pos] = sb[newpos];
sb[newpos] = c;
s = sb.ToString();
}
static string Reverse(string text)
{
char[] charArray = text.ToCharArray();
Array.Reverse(charArray);
return new string(charArray);
}
}