裏 RjpWiki

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

崩れないように積み上げて!

2017年11月21日 | ブログラミング

崩れないように積み上げて!

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

直方体の箱を重ねて置くことを考えます。
ただし、上の箱は下の箱よりも小さくないと、崩れてしまう可能性があります。
そこで、大きな箱の上に小さな箱を置くことを考えます。
ここで「小さい」とは縦と横の長さがともに短いことにします。
つまり、中央に重ねて置くと、上から見たときに下の箱の輪郭が見えるようにします。
また、箱は縦か横方向に綺麗に置くものとし、斜めに傾けて置くことはありません。
m 個の箱を用意したとき、その上面の面積の和が n でした。
このような箱のサイズの組み合わせが何通りあるか求めてください。
ただし、辺の長さはいずれも正の整数とし、箱の高さは考えないものとします。
なお、同じサイズの箱でも縦と横の置き方が違う場合は別々にカウントします。
例えば、m = 3, n = 20 のとき、上から見ると以下の4通りがあります。

同様に、m = 2, n = 14 のとき、上から見ると以下の8通りがあります。

標準入力から m, n が与えられたとき、その箱のサイズの組み合わせを求め、その数を標準出力に出力してください。
なお、m, n は 0 < m < n < 250を満たす整数とします。
【入出力サンプル】
標準入力
3 20
標準出力
4

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

所詮 R では m < 5 程度まで

Div = function(m, n) {
    d = NULL
    if (m == 2) {
        for (i1 in n:1) {
            for (i2 in i1:1) {
                if (i1 + i2 == n) {
                    d = rbind(d, c(i1, i2))
                }
            }
        }
    } else if (m == 3) {
        for (i1 in n:1) {
            for (i2 in i1:1) {
                i12 = i1 + i2
                if (i1 + i2 >= n)
                    next
                for (i3 in i2:1) {
                    if (i1 + i2 + i3 == n) {
                        d = rbind(d, c(i1, i2, i3))
                    }
                }
            }
        }
    } else if (m == 4) {
        for (i1 in n:1) {
            for (i2 in i1:1) {
                i12 = i1 + i2
                if (i12 >= n)
                    next
                for (i3 in i2:1) {
                    i123 = i12 + i3
                    if (i123 >= n)
                        next
                    for (i4 in i3:1) {
                        if (i1 + i2 + i3 + i4 == n) {
                            d = rbind(d, c(i1, i2, i3, i4))
                        }
                    }
                }
            }
        }
    }
    return(d)
}

f = function(m, n) {
    D = Div(m, n)
    count = 0
    for (k in 1:nrow(D)) {
        d = D[k, ]
        a = vector("list", m)
        for (i in 1:m) {
            x = 1:floor(sqrt(d[i]))
            temp = x[(d[i]%/%x) == (d[i]/x)]
            temp = sort(unique(c(temp, d[i]/temp)))
            a[[i]] = temp
        }
        if (m == 2) {
            for (i1 in 1:length(a[[1]])) {
                a1 = a[[1]][i1]
                b1 = d[1]/a1
                for (i2 in 1:length(a[[2]])) {
                    a2 = a[[2]][i2]
                    b2 = d[2]/a2
                    if (a1 > a2 && b1 > b2) {
                        count = count + 1
                    }

                }
            }
        } else if (m == 3) {
            for (i1 in 1:length(a[[1]])) {
                a1 = a[[1]][i1]
                b1 = d[1]/a1
                for (i2 in 1:length(a[[2]])) {
                    a2 = a[[2]][i2]
                    b2 = d[2]/a2
                    for (i3 in 1:length(a[[3]])) {
                        a3 = a[[3]][i3]
                        b3 = d[3]/a3
                        if (a1 > a2 && a2 > a3 && b1 > b2 && b2 > b3) {
                            count = count + 1
                        }
                    }
                }
            }
        } else if (m == 4) {
            for (i1 in 1:length(a[[1]])) {
                a1 = a[[1]][i1]
                b1 = d[1]/a1
                for (i2 in 1:length(a[[2]])) {
                    a2 = a[[2]][i2]
                    if (a2 >= a1)
                        next
                    b2 = d[2]/a2
                    if (b2 >= b1)
                        next
                    for (i3 in 1:length(a[[3]])) {
                        a3 = a[[3]][i3]
                        if (a3 >= a2)
                            next
                        b3 = d[3]/a3
                        if (b3 >= b2)
                            next
                        for (i4 in 1:length(a[[4]])) {
                            a4 = a[[4]][i4]
                            if (a4 >= a3)
                                next
                            b4 = d[4]/a4
                            if (b4 >= b3)
                                next
                            count = count + 1
                        }
                    }
                }
            }
        }
    }
    cat(count)
}

system.time(f(2, 14)) # 8
system.time(f(3, 20)) # 4
system.time(f(4, 100)) # 466 # 1.694 sec.


n ごとに最適化して Java プログラムを書くことで,どうにか実行時間を 1 秒以内に収まる

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

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

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