using System;
using System.Collections.Generic;
using System.Linq;
class Program
{
static string InputPattern = "InputX";
static List<string> GetInputList()
{
var WillReturn = new List<string>();
if (InputPattern == "Input1") {
WillReturn.Add("5");
WillReturn.Add("RBRBB");
WillReturn.Add("RBRRR");
WillReturn.Add("RRRBR");
WillReturn.Add("RBBRB");
WillReturn.Add("BBRBR");
//3
}
else if (InputPattern == "Input2") {
WillReturn.Add("5");
WillReturn.Add("RBBBB");
WillReturn.Add("BBBBB");
WillReturn.Add("BBBBB");
WillReturn.Add("BBBBB");
WillReturn.Add("BBBBR");
//7
}
else if (InputPattern == "Input3") {
WillReturn.Add("10");
WillReturn.Add("RRBBBBBBBB");
WillReturn.Add("BRRBBBBBBB");
WillReturn.Add("BBRRBBBBBB");
WillReturn.Add("BBBRRBBBBB");
WillReturn.Add("BBBBRRBBBB");
WillReturn.Add("BBBBBRRBBB");
WillReturn.Add("BBBBBBRRBB");
WillReturn.Add("BBBBBBBRRB");
WillReturn.Add("BBBBBBBBRR");
WillReturn.Add("BBBBBBBBBR");
//2
}
else if (InputPattern == "Input4") {
WillReturn.Add("17");
WillReturn.Add("RBBRRBRRRRRBBBBBB");
WillReturn.Add("BBRBRBRRBRRBRRBBR");
WillReturn.Add("BRBRBBBRBBRBBRBBB");
WillReturn.Add("RBRRBBBBBBRRBRRRR");
WillReturn.Add("RRRRRBRBRRRBBRBBR");
WillReturn.Add("RRRRRBRRBRBBRRRBB");
WillReturn.Add("BBBRRRBRBRBBRRRBB");
WillReturn.Add("BBRRRBRBBBRBRRRBR");
WillReturn.Add("RRBBBBBBBBBBBRBRR");
WillReturn.Add("RRRBRRBRBRBRBRBBB");
WillReturn.Add("RRBRRRRBRBRRBRBBR");
WillReturn.Add("RRRBBRBRBBBRBBRBR");
WillReturn.Add("BBRBBRRBRRRBBRBBB");
WillReturn.Add("BBBRBRRRRRRRBBRBB");
WillReturn.Add("RRRRRBRBRBBRRBRRR");
WillReturn.Add("BRRRRBBBRRRBRRBBB");
WillReturn.Add("BBRRBBRRRBBBRBBBR");
//8
}
else {
string wkStr;
while ((wkStr = Console.ReadLine()) != null) WillReturn.Add(wkStr);
}
return WillReturn;
}
static long UB;
static char[,] mBanArrSei;
static char[,] mBanArrRev;
static void Main()
{
List<string> InputList = GetInputList();
mBanArrSei = CreateBanArr(InputList.Skip(1));
UB = mBanArrSei.GetUpperBound(0);
mBanArrRev = new char[UB + 1, UB + 1];
for (long X = 0; X <= UB; X++) {
for (long Y = 0; Y <= UB; Y++) {
char CurrChar = mBanArrSei[X, Y];
if (CurrChar == 'B') {
mBanArrSei[X, Y] = '1';
mBanArrRev[X, Y] = '0';
}
else {
mBanArrSei[X, Y] = '0';
mBanArrRev[X, Y] = '1';
}
}
}
long Cost1 = Exec01BFS(mBanArrSei, 0, 0, UB, UB);
long Cost2 = Exec01BFS(mBanArrRev, UB, 0, 0, UB);
Console.WriteLine(Cost1 + Cost2);
}
struct JyoutaiDef
{
internal long CurrX;
internal long CurrY;
internal long Val;
}
// 最小コストを返す
static long Exec01BFS(char[,] pBanArr, long pStaX, long pStaY, long pGoalX, long pGoalY)
{
var InsLinkedList = new LinkedList<JyoutaiDef>();
JyoutaiDef WillEnqueue;
WillEnqueue.CurrX = pStaX;
WillEnqueue.CurrY = pStaY;
WillEnqueue.Val = 0;
InsLinkedList.AddFirst(WillEnqueue);
long Answer = long.MaxValue;
var VisitedSet = new HashSet<long>();
while (InsLinkedList.Count() > 0) {
JyoutaiDef Dequeued = InsLinkedList.First();
InsLinkedList.RemoveFirst();
//クリア判定
if (Dequeued.CurrX == pGoalX && Dequeued.CurrY == pGoalY) {
Answer = Math.Min(Answer, Dequeued.Val);
continue;
}
if (Dequeued.Val >= Answer) continue;
Action<long, long> PushAct = (pNewX, pNewY) =>
{
if (pNewX < 0 || UB < pNewX) return;
if (pNewY < 0 || UB < pNewY) return;
// 最訪防止
long CurrHash = GetHash(pNewX, pNewY);
if (VisitedSet.Add(CurrHash) == false) {
return;
}
WillEnqueue.CurrX = pNewX;
WillEnqueue.CurrY = pNewY;
WillEnqueue.Val = Dequeued.Val;
bool WillAddFirst = true;
if (pBanArr[pNewX, pNewY] == '1') {
WillEnqueue.Val++;
WillAddFirst = false;
}
if (WillAddFirst) {
InsLinkedList.AddFirst(WillEnqueue);
}
else {
InsLinkedList.AddLast(WillEnqueue);
}
};
PushAct(Dequeued.CurrX, Dequeued.CurrY - 1);
PushAct(Dequeued.CurrX, Dequeued.CurrY + 1);
PushAct(Dequeued.CurrX - 1, Dequeued.CurrY);
PushAct(Dequeued.CurrX + 1, Dequeued.CurrY);
}
return Answer;
}
// 座標のハッシュ値を返す
static long GetHash(long pX, long pY)
{
return pX * 1000 + pY;
}
////////////////////////////////////////////////////////////////
// IEnumerable<string>をcharの2次元配列に設定する
////////////////////////////////////////////////////////////////
static char[,] CreateBanArr(IEnumerable<string> pStrEnum)
{
var StrList = pStrEnum.ToList();
if (StrList.Count == 0) {
return new char[0, 0];
}
int UB_X = StrList[0].Length - 1;
int UB_Y = StrList.Count - 1;
char[,] WillReturn = new char[UB_X + 1, UB_Y + 1];
for (int Y = 0; Y <= UB_Y; Y++) {
for (int X = 0; X <= UB_X; X++) {
WillReturn[X, Y] = StrList[Y][X];
}
}
return WillReturn;
}
////////////////////////////////////////////////////////////////
// 2次元配列(char型)のデバッグ出力
////////////////////////////////////////////////////////////////
static void PrintBan(char[,] pBanArr)
{
var sb = new System.Text.StringBuilder();
for (int Y = 0; Y <= pBanArr.GetUpperBound(1); Y++) {
for (int X = 0; X <= pBanArr.GetUpperBound(0); X++) {
sb.Append(pBanArr[X, Y]);
}
sb.AppendLine();
}
Console.Write(sb.ToString());
}
}