裏 RjpWiki

Julia ときどき R, Python によるコンピュータプログラム,コンピュータ・サイエンス,統計学

魔方陣で最大値?

2017年01月09日 | ブログラミング

魔方陣で最大値?

締め切りが 2017/01/09 10:00 AM なので,その 1 分後に投稿されるように予約

設問

4×4の魔方陣は1〜16までの数字を1度ずつ使ったもので、以下の左図のようなものがあります。



魔方陣は縦、横、斜めのすべての列について、その和が等しいという特徴があります。

魔方陣において、左上のマスからスタートして、右か下の隣り合うマスへの移動を繰り返して最短距離で右下のマスまで移動します。
このとき、経由したマスの数の和が最大になるような移動経路を考えます。
上図の魔方陣の場合、上図右のように移動すると和は 67 になります。

標準入力から整数 n が与えられたとき、4×4のすべての魔方陣に対してこのような移動経路を求め、その和が n になる魔方陣の個数を求め、標準出力に出力してください。

4×4の魔方陣は全部で7,040個存在することが知られています。
その中で、n=54のときは以下の2パターンに回転や鏡像を含めたものが全部で8通りありますので、以下のような入出力になります。



【入出力サンプル】
標準入力
54

標準出力
8

=================

R で書くと制限時間(1 秒)に引っかかるので,AWK で書いた(Java でも C でもよいけど)
魔方陣の生成部分はネットを参考に

func = function(num) {
    route = function(table) {
        sums = integer(20)
        sums[1] = table[1, 2] + table[1, 3] + table[1, 4] + table[2, 4] + table[3, 4]
        sums[2] = table[1, 2] + table[1, 3] + table[2, 3] + table[2, 4] + table[3, 4]
        sums[3] = table[1, 2] + table[1, 3] + table[2, 3] + table[3, 3] + table[3, 4]
        sums[4] = table[1, 2] + table[1, 3] + table[2, 3] + table[3, 3] + table[4, 3]
        sums[5] = table[1, 2] + table[2, 2] + table[2, 3] + table[2, 4] + table[3, 4]
        sums[6] = table[1, 2] + table[2, 2] + table[2, 3] + table[3, 3] + table[3, 4]
        sums[7] = table[1, 2] + table[2, 2] + table[2, 3] + table[3, 3] + table[4, 3]
        sums[8] = table[1, 2] + table[2, 2] + table[3, 2] + table[3, 3] + table[3, 4]
        sums[9] = table[1, 2] + table[2, 2] + table[3, 2] + table[3, 3] + table[4, 3]
        sums[10] = table[1, 2] + table[2, 2] + table[3, 2] + table[4, 2] + table[4, 3]
        sums[11] = table[2, 1] + table[2, 2] + table[2, 3] + table[2, 4] + table[3, 4]
        sums[12] = table[2, 1] + table[2, 2] + table[2, 3] + table[3, 3] + table[3, 4]
        sums[13] = table[2, 1] + table[2, 2] + table[2, 3] + table[3, 3] + table[4, 3]
        sums[14] = table[2, 1] + table[2, 2] + table[3, 2] + table[3, 3] + table[3, 4]
        sums[15] = table[2, 1] + table[2, 2] + table[3, 2] + table[3, 3] + table[4, 3]
        sums[16] = table[2, 1] + table[2, 2] + table[3, 2] + table[4, 2] + table[4, 3]
        sums[17] = table[2, 1] + table[3, 1] + table[3, 2] + table[3, 3] + table[3, 4]
        sums[18] = table[2, 1] + table[3, 1] + table[3, 2] + table[3, 3] + table[4, 3]
        sums[19] = table[2, 1] + table[3, 1] + table[3, 2] + table[4, 2] + table[4, 3]
        sums[20] = table[2, 1] + table[3, 1] + table[4, 1] + table[4, 2] + table[4, 3]
        max(sums + table[1, 1] + table[4, 4]) == num
    }

    table = matrix(0, 4, 4)
    used = logical(16)
    count = 0
    for (a in 1:13) {
        used[a] = TRUE
        for (d in (a + 1):15) {
            used[d] = TRUE
            for (m in (d + 1):16) {
                p = 34 - a - d - m
                if (p < a) break
                if (p > 16) next
                if (used[p]) next
                if (p == m) next
                used[m] = used[p] = TRUE
                for (f in 1:16) {
                    if (used[f]) next
                    k = 34 - a - f - p
                    if (k < 1) break
                    if (k > 16) next
                    if (used[k]) next
                    if (f == k) next
                    used[f] = used[k] = TRUE
                    for (b in 1:16) {
                        if (used[b]) next
                        c = 34 - a - b - d
                        if (c < 1) break
                        if (c > 16) next
                        if (used[c]) next
                        if (b == c) next
                        used[b] = used[c] = TRUE
                        for (g in 1:16) {
                            if (used[g]) next
                            j = 34 - d - g - m
                            if (j < 1) break
                            if (j > 16) next
                            if (used[j]) next
                            if (j == g) next
                            o = 34 - c - g - k
                            if (o < 1) break
                            if (o > 16) next
                            if (used[o]) next
                            if (o == g || o == j) next
                            n = 34 - b - f - j
                            if (n > 16) break
                            if (n < 1) next
                            if (used[n]) next
                            if (n == g || n == j || n == o) next
                            used[g] = used[j] = used[o] = used[n] = TRUE
                            for (e in 1:16) {
                                if (used[e]) next
                                h = 34 - e - f - g
                                if (h < 1) break
                                if (h > 16) next
                                if (used[h]) next
                                if (h == e) next
                                i = 34 - a - e - m
                                if (i < 1) break
                                if (i > 16) next
                                if (used[i]) next
                                if (i == e || i == h) next
                                l = 34 - d - h - p
                                if (l > 16) break
                                if (l < 1) next
                                if (used[l]) next
                                if (l == e || l == h || l == i) next
                                table[1, 1] = a
                                table[1, 2] = b
                                table[1, 3] = c
                                table[1, 4] = d
                                table[2, 1] = e
                                table[2, 2] = f
                                table[2, 3] = g
                                table[2, 4] = h
                                table[3, 1] = i
                                table[3, 2] = j
                                table[3, 3] = k
                                table[3, 4] = l
                                table[4, 1] = m
                                table[4, 2] = n
                                table[4, 3] = o
                                table[4, 4] = p
                                table2 = table[, 4:1]
                                table3 = t(table)
                                table4 = table3[, 4:1]
                                table5 = t(table2)
                                table6 = table5[, 4:1]
                                table7 = t(table4)
                                table8 = table7[, 4:1]
                                ans = sum(route(table), route(table2), route(table3), route(table4), route(table5),
                                    route(table6), route(table7), route(table8))
                                count = count + ans
                            }
                            used[g] = used[j] = used[o] = used[n] = FALSE
                        }
                        used[b] = used[c] = FALSE
                    }
                    used[f] = used[k] = FALSE
                }
                used[m] = used[p] = FALSE
            }
            used[d] = FALSE
        }
        used[a] = FALSE
    }
    count
}

コメント
  • X
  • Facebookでシェアする
  • はてなブックマークに追加する
  • LINEでシェアする

PVアクセスランキング にほんブログ村

PVアクセスランキング にほんブログ村