トップページに戻る    次の増井さんの書籍の問題へ    前の増井さんの書籍の問題へ

Q34 飛車と角の利き


C#のソース

using System;
using System.Collections.Generic;

class Program
{
    const int UB = 9 - 1;

    static void Main()
    {
        int Answer = 0;

        //角は、0からUB/2の範囲に配置可とする
        for (int KakuX = 0; KakuX <= UB / 2; KakuX++) {
            for (int KakuY = 0; KakuY <= UB / 2; KakuY++) {
                int wkKikiSum = DeriveKikiSum(KakuX, KakuY);

                //角の配置の、対称点があれば、場合の数を調整
                if (UB - KakuX != KakuX) wkKikiSum *= 2;
                if (UB - KakuY != KakuY) wkKikiSum *= 2;
                Answer += wkKikiSum;
            }
        }
        Console.WriteLine(Answer);
    }

    //角の座標を引数とし、飛車の全配置での、利きマスの合計を求める
    static int DeriveKikiSum(int pKakuX, int pKakuY)
    {
        int WillReturn = 0;
        for (int HisyaX = 0; HisyaX <= UB; HisyaX++) {
            for (int HisyaY = 0; HisyaY <= UB; HisyaY++) {
                if (HisyaX == pKakuX && HisyaY == pKakuY)
                    continue;
                WillReturn += DeriveKikiSum(pKakuX, pKakuY, HisyaX, HisyaY);
            }
        }
        return WillReturn;
    }

    //角と飛車の座標を引数として、利きマスの合計を求める
    static int DeriveKikiSum(int pKakuX, int pKakuY, int pHisyaX, int pHisyaY)
    {
        var KikiMasuSet = new HashSet<string>();

        //角の右上の利き
        for (int X = pKakuX + 1, Y = pKakuY - 1; X <= UB && 0 <= Y; X++, Y--) {
            if (X == pHisyaX && Y == pHisyaY) break;
            KikiMasuSet.Add(string.Format("{0},{1}", X, Y));
        }
        //角の右下の利き
        for (int X = pKakuX + 1, Y = pKakuY + 1; X <= UB && Y <= UB; X++, Y++) {
            if (X == pHisyaX && Y == pHisyaY) break;
            KikiMasuSet.Add(string.Format("{0},{1}", X, Y));
        }
        //角の左下の利き
        for (int X = pKakuX - 1, Y = pKakuY + 1; 0 <= X && Y <= UB; X--, Y++) {
            if (X == pHisyaX && Y == pHisyaY) break;
            KikiMasuSet.Add(string.Format("{0},{1}", X, Y));
        }
        //角の左上の利き
        for (int X = pKakuX - 1, Y = pKakuY - 1; 0 <= X && 0 <= Y; X--, Y--) {
            if (X == pHisyaX && Y == pHisyaY) break;
            KikiMasuSet.Add(string.Format("{0},{1}", X, Y));
        }

        //飛車の上の利き
        for (int Y = pHisyaY - 1; 0 <= Y; Y--) {
            if (pHisyaX == pKakuX && Y == pKakuY) break;
            KikiMasuSet.Add(string.Format("{0},{1}", pHisyaX, Y));
        }
        //飛車の右の利き
        for (int X = pHisyaX + 1; X <= UB; X++) {
            if (X == pKakuX && pHisyaY == pKakuY) break;
            KikiMasuSet.Add(string.Format("{0},{1}", X, pHisyaY));
        }
        //飛車の下の利き
        for (int Y = pHisyaY + 1; Y <= UB; Y++) {
            if (pHisyaX == pKakuX && Y == pKakuY) break;
            KikiMasuSet.Add(string.Format("{0},{1}", pHisyaX, Y));
        }
        //飛車の左の利き
        for (int X = pHisyaX - 1; 0 <= X; X--) {
            if (X == pKakuX && pHisyaY == pKakuY) break;
            KikiMasuSet.Add(string.Format("{0},{1}", X, pHisyaY));
        }
        return KikiMasuSet.Count;
    }
}


実行結果

149424


解説

角の配置位置を制限して、
計算量を4分の1に減らしてます。