4匹のカエルが、左から番号の大きい順に葉の上に並んでいる。 このカエルを、番号の小さい順に並べ替えてほしい。 カエルは左右両隣の葉に飛び移ることができ、 また、もう1つ向こうの葉が空いている場合は、他のカエルを飛び越して移動することもできる。 ただし、1枚の葉に同時に2匹以上のカエルが乗ることはできない。 さて、カエルを指定した順に並び替えるにはどうすればよいだろうか? カエルの整列 : クイズ&パズルの部屋「Quizzical Days.」
using System; using System.Collections.Generic; using System.Linq; class Program { private struct JyoutaiDef { internal int[] FrogArr; internal List<int[]> Log; } static void Main() { var que = new Queue<JyoutaiDef>(); JyoutaiDef WillEnqueue; WillEnqueue.FrogArr = new int[5] { 4, 3, 2, 1, 0 }; WillEnqueue.Log = new List<int[]>() { WillEnqueue.FrogArr }; que.Enqueue(WillEnqueue); int MaxLevel = int.MaxValue; int AnswerCnt = 0; while (que.Count > 0) { JyoutaiDef Dequeued = que.Dequeue(); if (MaxLevel < Dequeued.Log.Count) continue; if (Dequeued.FrogArr.SequenceEqual(new int[] { 1, 2, 3, 4, 0 }) || Dequeued.FrogArr.SequenceEqual(new int[] { 0, 1, 2, 3, 4 })) { Console.WriteLine("解{0}を発見しました。", ++AnswerCnt); PrintFrogArrLog(Dequeued.Log); if (MaxLevel > Dequeued.Log.Count) MaxLevel = Dequeued.Log.Count; continue; } int IndZero = Array.IndexOf<int>(Dequeued.FrogArr, 0); Action<int> EnqueSyori = (IndChanged) => { WillEnqueue.FrogArr = (int[])Dequeued.FrogArr.Clone(); WillEnqueue.FrogArr[IndZero] = WillEnqueue.FrogArr[IndChanged]; WillEnqueue.FrogArr[IndChanged] = 0; //既存の配置だったら枝切り if (Dequeued.Log.Exists(X => X.SequenceEqual(WillEnqueue.FrogArr))) { return; } WillEnqueue.Log = new List<int[]>(Dequeued.Log); WillEnqueue.Log.Add(WillEnqueue.FrogArr); que.Enqueue(WillEnqueue); }; if (1 <= IndZero) EnqueSyori(IndZero - 1); //0の1つ左 if (2 <= IndZero) EnqueSyori(IndZero - 2); //0の2つ左 int UB = Dequeued.FrogArr.GetUpperBound(0); if (IndZero <= UB - 1) EnqueSyori(IndZero + 1); //0の1つ右 if (IndZero <= UB - 2) EnqueSyori(IndZero + 2); //0の2つ右 } } static void PrintFrogArrLog(List<int[]> pFrogArrLog) { int Level = 0; foreach (int[] AnyArr in pFrogArrLog) { Console.Write("LV{0,2}=", ++Level); foreach (int AnyInt in AnyArr) { Console.Write("{0},", AnyInt); } Console.WriteLine(); } } }
解1を発見しました LV 1=4,3,2,1,0, LV 2=4,3,2,0,1, LV 3=4,0,2,3,1, LV 4=0,4,2,3,1, LV 5=2,4,0,3,1, LV 6=2,4,1,3,0, LV 7=2,4,1,0,3, LV 8=2,0,1,4,3, LV 9=0,2,1,4,3, LV10=1,2,0,4,3, LV11=1,2,3,4,0, 解2を発見しました LV 1=4,3,2,1,0, LV 2=4,3,0,1,2, LV 3=4,0,3,1,2, LV 4=4,1,3,0,2, LV 5=4,1,3,2,0, LV 6=4,1,0,2,3, LV 7=0,1,4,2,3, LV 8=1,0,4,2,3, LV 9=1,2,4,0,3, LV10=1,2,0,4,3, LV11=1,2,3,4,0, 解3を発見しました LV 1=4,3,2,1,0, LV 2=4,3,0,1,2, LV 3=0,3,4,1,2, LV 4=3,0,4,1,2, LV 5=3,1,4,0,2, LV 6=3,1,4,2,0, LV 7=3,1,0,2,4, LV 8=0,1,3,2,4, LV 9=1,0,3,2,4, LV10=1,2,3,0,4, LV11=1,2,3,4,0, 解4を発見しました LV 1=4,3,2,1,0, LV 2=4,3,0,1,2, LV 3=4,3,1,0,2, LV 4=4,0,1,3,2, LV 5=0,4,1,3,2, LV 6=1,4,0,3,2, LV 7=1,4,2,3,0, LV 8=1,4,2,0,3, LV 9=1,0,2,4,3, LV10=1,2,0,4,3, LV11=1,2,3,4,0,
ListジェネリックのExistsメソッドの引数の、Predicateデリゲートで LINQのSequenceEqual拡張メソッドを使って枝切りしてます。 MSDN --- List<T>.Existsメソッド MSDN --- Enumerable.SequenceEqual<TSource>メソッド