トップページに戻る
次のC#のサンプルへ
前のC#のサンプルへ
Problem166 十字
問題
0 <= d <= 9 な d で埋められた 4x4 の格子がある.
以下の格子では, それぞれの行, 列の和が12となる. さらに, 斜めの和も12となる.
6 3 3 0
5 0 4 3
0 7 1 4
1 2 4 5
0 <= d <= 9 な d で 4x4 の格子を,
それぞれの行, 列, 斜めの和が同じとなるように埋める方法は何通りあるか?
ソース
using System;
using System.Collections.Generic;
using System.Linq;
class Program
{
const int UB = 3;
struct KouhoInfoDef
{
internal int A;
internal int B;
internal int C;
internal int D;
internal int SumVal;
}
static KouhoInfoDef[] mKouhoArr;
static Dictionary<int, int> mStaIndDict = new Dictionary<int, int>();
static void Main()
{
var sw = System.Diagnostics.Stopwatch.StartNew();
DeriveKouhoArr();
int UB = mKouhoArr.GetUpperBound(0);
int AnswerCnt = 0;
foreach (KouhoInfoDef Each1 in mKouhoArr) {
foreach (KouhoInfoDef Each2 in mKouhoArr) {
int Teiwa = Each1.A + Each1.B + Each2.A + Each2.B;
//Y=1の行の横計
if (Each1.C + Each1.D + Each2.C + Each2.D != Teiwa)
continue;
//対称解の除外
if (Each1.A > Each2.B) continue;
if (Each1.B > Each2.A) continue;
int NeedSum3 = 2 * Teiwa - Each1.SumVal;
for (int I = mStaIndDict[NeedSum3]; I <= UB; I++) {
KouhoInfoDef Each3 = mKouhoArr[I];
if (Each3.SumVal > NeedSum3) break;
//X=0の列の縦計
if (Each1.A + Each1.C + Each3.A + Each3.C != Teiwa)
continue;
//X=1の列の縦計
if (Each1.B + Each1.D + Each3.B + Each3.D != Teiwa)
continue;
//斜め計
if (Each2.B + Each2.C + Each3.B + Each3.C != Teiwa)
continue;
int NeedSum4 = 2 * Teiwa - Each3.SumVal;
for (int J = mStaIndDict[NeedSum4]; J <= UB; J++) {
KouhoInfoDef Each4 = mKouhoArr[J];
if (Each4.SumVal > NeedSum4) break;
//Y=2の行の横計
if (Each3.A + Each3.B + Each4.A + Each4.B != Teiwa)
continue;
//Y=3の行の横計
if (Each3.C + Each3.D + Each4.C + Each4.D != Teiwa)
continue;
//X=2の列の縦計
if (Each2.A + Each2.C + Each4.A + Each4.C != Teiwa)
continue;
//X=3の列の縦計
if (Each2.B + Each2.D + Each4.B + Each4.D != Teiwa)
continue;
//斜め計
if (Each1.A + Each1.D + Each4.A + Each4.D != Teiwa)
continue;
//除外した対称解の分を計上
int AnswerPattern = 1;
if (Each1.A < Each2.B) AnswerPattern *= 2;
if (Each1.B < Each2.A) AnswerPattern *= 2;
AnswerCnt += AnswerPattern;
}
}
}
}
Console.WriteLine("解は{0}通り。経過時間={1}", AnswerCnt, sw.Elapsed);
}
static void DeriveKouhoArr()
{
var KouhoList = new List<KouhoInfoDef>();
for (int A = 0; A <= 9; A++) {
for (int B = 0; B <= 9; B++) {
for (int C = 0; C <= 9; C++) {
for (int D = 0; D <= 9; D++) {
KouhoInfoDef WillAdd;
WillAdd.A = A;
WillAdd.B = B;
WillAdd.C = C;
WillAdd.D = D;
WillAdd.SumVal = A + B + C + D;
KouhoList.Add(WillAdd);
}
}
}
}
//合計値でソートしておく
mKouhoArr = KouhoList.OrderBy(X => X.SumVal).ToArray();
//合計値ごとの開始の添字を求めておく
for (int I = 0; I <= mKouhoArr.GetUpperBound(0); I++) {
if (mStaIndDict.ContainsKey(mKouhoArr[I].SumVal) == false) {
mStaIndDict.Add(mKouhoArr[I].SumVal, I);
}
}
}
}
実行結果
解は7130034通り。経過時間=00:00:18.3673578
解説
左上4マス + 左下4マス = 2*定和
と
左下4マス + 右下4マス = 2*定和
が成立することを使ってます。