トップページに戻る    次のC#のサンプルへ    前のC#のサンプルへ

8-27 油分け算3 {16,9,7}を{8,8,0}

問題

16リットル入りの容器に油がいっぱい入っており、
他に9リットルと7リットルの容器がある。
これらの容器だけを使って、油を正確に8リットルずつ分けるには
どうすればよいか。

 ̄torito_ パズル遊びへの招待 1−7.油分け算


ソース

using System;
using System.Collections.Generic;

class Program
{
    struct JyoutaiDef
    {
        internal int Youki16;
        internal int Youki09;
        internal int Youki07;
        internal List<string> Log;
    }

    static void Main()
    {
        var que = new Queue<JyoutaiDef>();
        JyoutaiDef WillEnqueue;
        WillEnqueue.Youki16 = 16;
        WillEnqueue.Youki09 = WillEnqueue.Youki07 = 0;
        WillEnqueue.Log = new List<string>();
        WillEnqueue.Log.Add(MakeOneLog(16, 0, 0));
        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.Youki16 == 8 && Dequeued.Youki09 == 8) {
                Console.WriteLine("解{0}を発見しました。", ++AnswerCnt);
                Dequeued.Log.ForEach(X => Console.WriteLine(X));
                if (MaxLevel > Dequeued.Log.Count)
                    MaxLevel = Dequeued.Log.Count;
                continue;
            }

            Action<int, int, int> EnqueSyori = (pYouki16, pYouki09, pYouki07) =>
            {
                WillEnqueue.Youki16 = pYouki16;
                WillEnqueue.Youki09 = pYouki09;
                WillEnqueue.Youki07 = pYouki07;

                string NewLog = MakeOneLog(pYouki16, pYouki09, pYouki07);
                if (Dequeued.Log.Contains(NewLog)) return;

                WillEnqueue.Log = new List<string>(Dequeued.Log);
                WillEnqueue.Log.Add(NewLog);
                que.Enqueue(WillEnqueue);
            };

            if (Dequeued.Youki16 > 0) {
                if (Dequeued.Youki09 < 9) {
                    int Aki = 9 - Dequeued.Youki09;
                    int Fill = Math.Min(Aki, Dequeued.Youki16);
                    EnqueSyori(Dequeued.Youki16 - Fill, Dequeued.Youki09 + Fill, Dequeued.Youki07);
                }
                if (Dequeued.Youki07 < 7) {
                    int Aki = 7 - Dequeued.Youki07;
                    int Fill = Math.Min(Aki, Dequeued.Youki16);
                    EnqueSyori(Dequeued.Youki16 - Fill, Dequeued.Youki09, Dequeued.Youki07 + Fill);
                }
            }
            if (Dequeued.Youki09 > 0) {
                if (Dequeued.Youki16 < 16) {
                    int Aki = 16 - Dequeued.Youki16;
                    int Fill = Math.Min(Aki, Dequeued.Youki09);
                    EnqueSyori(Dequeued.Youki16 + Fill, Dequeued.Youki09 - Fill, Dequeued.Youki07);
                }
                if (Dequeued.Youki07 < 7) {
                    int Aki = 7 - Dequeued.Youki07;
                    int Fill = Math.Min(Aki, Dequeued.Youki09);
                    EnqueSyori(Dequeued.Youki16, Dequeued.Youki09 - Fill, Dequeued.Youki07 + Fill);
                }
            }
            if (Dequeued.Youki07 > 0) {
                if (Dequeued.Youki16 < 16) {
                    int Aki = 16 - Dequeued.Youki16;
                    int Fill = Math.Min(Aki, Dequeued.Youki07);
                    EnqueSyori(Dequeued.Youki16 + Fill, Dequeued.Youki09, Dequeued.Youki07 - Fill);
                }
                if (Dequeued.Youki09 < 9) {
                    int Aki = 9 - Dequeued.Youki09;
                    int Fill = Math.Min(Aki, Dequeued.Youki07);
                    EnqueSyori(Dequeued.Youki16, Dequeued.Youki09 + Fill, Dequeued.Youki07 - Fill);
                }
            }
        }
    }

    static string MakeOneLog(int pYouki16, int pYouki09, int pYouki07)
    {
        return string.Format("容器16={0,2},容器9={1},容器7={2}", pYouki16, pYouki09, pYouki07);
    }
}


実行結果

解1を発見しました。
容器16=16,容器9=0,容器7=0
容器16= 7,容器9=9,容器7=0
容器16= 7,容器9=2,容器7=7
容器16=14,容器9=2,容器7=0
容器16=14,容器9=0,容器7=2
容器16= 5,容器9=9,容器7=2
容器16= 5,容器9=4,容器7=7
容器16=12,容器9=4,容器7=0
容器16=12,容器9=0,容器7=4
容器16= 3,容器9=9,容器7=4
容器16= 3,容器9=6,容器7=7
容器16=10,容器9=6,容器7=0
容器16=10,容器9=0,容器7=6
容器16= 1,容器9=9,容器7=6
容器16= 1,容器9=8,容器7=7
容器16= 8,容器9=8,容器7=0


解説

幅優先探索は、便利ですねぇ