ここに,それぞれ3個の数からなる組が3組ある。 (12,18,35) (10,27,28) (14,15,36) それぞれの組について,3個の数の和をとるとすべて65になる。 また積は7560となり,やはり同じになっている。 ではこれを4組に拡張し, 「3数づつが4組あり,各組の和をとっても積をとっても同じになる」という数の組み合わせをひとつ見つけてほしい。 ここに登場する数はすべて正の整数で,同じ数は使わない。余裕のある方は5組でも挑戦していただきたい。
using System;
using System.Collections.Generic;
using System.Linq;
class Program
{
const int Jyougen = 135;
static void Main()
{
Solve(3);
Solve(4);
Solve(5);
}
struct JyoutaiDef
{
internal int Level;
internal List<int[]> NumArrList;
internal int SumVal;
internal int ProdVal;
}
//組の数を指定して、解を求める
static void Solve(int pCombiCnt)
{
var sw = System.Diagnostics.Stopwatch.StartNew();
var stk = new Stack<JyoutaiDef>();
JyoutaiDef WillPush;
WillPush.Level = 0;
WillPush.NumArrList = new List<int[]>();
WillPush.SumVal = WillPush.ProdVal = 0;
stk.Push(WillPush);
while (stk.Count > 0) {
JyoutaiDef Popped = stk.Pop();
//クリア判定
if (Popped.Level == pCombiCnt) {
Console.WriteLine("{0}組の解を発見。経過時間={1}",
pCombiCnt, sw.Elapsed);
foreach (int[] EachNumArr in Popped.NumArrList) {
Array.ForEach(EachNumArr, X => Console.Write("{0},", X));
Console.WriteLine();
}
break;
}
var UsedNumSet = new HashSet<int>();
Popped.NumArrList.ForEach(X => UsedNumSet.UnionWith(X));
int[] FirstValArr = Popped.NumArrList.Select(X => X[0]).ToArray();
bool Calced = (Popped.Level >= 1);
for (int I = 1; I <= Jyougen; I++) {
if (Array.Exists(FirstValArr, X => X > I)) continue;
if (UsedNumSet.Contains(I)) continue;
if (Calced && Popped.ProdVal % I != 0) continue;
if (Calced && Popped.SumVal <= I * 3) break;
if (Calced && Popped.ProdVal <= I * I * I) break;
for (int J = I + 1; J <= Jyougen; J++) {
if (UsedNumSet.Contains(J)) continue;
if (Calced && Popped.ProdVal % J != 0) continue;
if (Calced && Popped.SumVal <= I + J * 2) break;
if (Calced && Popped.ProdVal <= I * J * J) break;
for (int K = J + 1; K <= Jyougen; K++) {
if (UsedNumSet.Contains(K)) continue;
int wkSumVal = I + J + K;
int wkProdVal = I * J * K;
if (Calced && Popped.SumVal < wkSumVal) break;
if (Calced && Popped.ProdVal < wkProdVal) break;
if (Calced && Popped.SumVal != wkSumVal) continue;
if (Calced && Popped.ProdVal != wkProdVal) continue;
WillPush.Level = Popped.Level + 1;
WillPush.NumArrList = new List<int[]>(Popped.NumArrList);
WillPush.NumArrList.Add(new int[] { I, J, K });
WillPush.SumVal = wkSumVal;
WillPush.ProdVal = wkProdVal;
stk.Push(WillPush);
}
}
}
}
}
}
3組の解を発見。経過時間=00:00:01.9579575 104,120,126, 105,117,128, 108,112,130, 4組の解を発見。経過時間=00:00:04.1358141 54,100,112, 56,90,120, 60,80,126, 63,75,128, 5組の解を発見。経過時間=00:00:24.3401239 11,84,90, 12,63,110, 15,44,126, 18,35,132, 22,28,135,
深さ優先探索で小まめに枝切りしてます。