0

私の状況

  • 私はN個の長方形を持っています
  • 長方形はすべて同じ形状です(たとえば、幅2インチx高さ1インチ)-幅と高さについては、このサイズをSwおよびShと呼びましょう。
  • これらの長方形をグリッドに配置して、スプレッドシートに表示されるように、長方形が完全に上下に隣接するようにします。
  • 私が必要としているのはこれです:N、Sw、Shが与えられた場合、これらの長方形を可能な限り最も正方形のような配置に積み重ねる行(R)と列(C)の数はいくつですか。
  • R&Cは、必要以上のセルを提供する可能性があることを理解しています(たとえば、N = 15、Sw = 1、Sh = 1の場合、R = 4、C = 4の場合、15個の長方形に対して16個の「スロット」が生成されます。これで問題ありません。
  • Sw = Shの場合、私の謙虚な数学のスキルで十分です-長方形の幅と高さが異なる場合-率直に言って、それは私を超えています。

いくつかの注意事項

  • はい、私はこの質問を読みました:長方形を積み重ねてスペースをできるだけ少なくし、いいえ、それは役に立ちませんでした。また、それは同じ質問ではありません。その質問は、サイズが異なる可能性のある長方形に関するものです。この質問では、長方形のサイズは同じです。
  • はい、wolfram.comなどで検索しましたが、運がありません。
  • 私は数学のバックグラウンドがないので、この問題の言い回し自体が答えを見つけるのを妨げている可能性があります-タイリング、解剖、分解に関連する検索を試しましたが、そこでも成功しませんでした

いくつかの例

the * indicates the edges of the rects
the | indicates that a cell is "filled-in"
Notice that not all R*C cells are filled in, but only and exactly N cells

IF N=1, Sw=2, Sh=1 THEN R=1, C=1

********
*||||||*
********

IF N=2, Sw=2, Sh=1 THEN R=2, C=1

********
*||||||*
********
*||||||*
********

IF N=3, Sw=2, Sh=1 THEN R=2, C=2


***************
*||||||*      *
***************
*||||||*||||||*
***************

IF N=4, Sw=2, Sh=1 THEN R=2, C=2


***************
*||||||*||||||*
***************
*||||||*||||||*
***************

IF N=5, Sw=2, Sh=1 THEN R=3, C=2


***************
*||||||*      *
***************
*||||||*||||||*
***************
*||||||*||||||*
***************

AaronofTomorrowの回答の実装

# Implementation of AaronofTomorrow's answer
# implemented in python 2.6
# reasonable output
# works in constant time

import math

def f( N, Sw, Sh ) :
    cols = math.sqrt( float(N) * float(Sh) / float(Sw) )
    cols = round(cols)
    rows = float(N) / float(cols)
    rows = math.ceil(rows)
    return (int(cols),int(rows))

ウィルの答えに触発された別の実装(2008年12月8日に更新)-これは私が最終的に使用したものです

# Another implementation inspired by Will's answer
# implemented in python 2.6
# reasonable output - a bit better in yielding more squarelike grids
# works in time proportional to number of rects
#
# strategy used it to try incrementaly adding a rect.
# if the resulting rect requires more space then two
# possibilities are checked - adding a new row or adding a new col
# the one with the best aspect ratio (1:1) will be chosen 


def g( N, Sw, Sh ) :
    slope = float(Sh)/float(Sw)
    cols = 1
    rows = 1
    for i in xrange( N ) :
        num_to_fit =i+1
        allocated_cells= cols* rows
        if ( num_to_fit <= allocated_cells ) :
            pass # do nothing
        else :
            hc,wc = float(Sh * rows), float(Sw * (cols+1))
            hr,wr = float(Sh * (rows+1)), float(Sw * cols)
            thetac = math.atan( hc/wc)
            thetar = math.atan( hr/wr)
            alpha = math.pi/4.0
            difr = abs(alpha-thetar)
            difc = abs(alpha-thetac)
            if ( difr < difc ) :
                rows = rows +1
            else:
                cols = cols + 1

    return (cols,rows)
4

4 に答える 4

2

Will Dean の応答に基づいて、(nCols に関して) 彼の式の導関数を見つけます。

-N*Sh / nCols + Sw

次に、それを 0 に設定し、nCols を求めます。次のようになります。

nCols = sqrt(N * Sh / Sw)

それを四捨五入すると、最適な列数が得られます。

cols = round(sqrt(N * Sh / Sw))
行 = ceil(N / cols)

于 2008-12-04T10:13:53.510 に答える
1

「最も正方形のような」は、「最も円のような」への道のりであることがわかると思います。これは、円周(周囲の長さ)が最小になるポイントです。

あなたの円周は2*nRows * Sh + 2 *nColsSwです。nRows nCols> = Nであることはご存知でしょう。次のビットでは、nRows * nCols=Nに単純化しても問題ないと思います。

それを試さずに、関数の()最小値を見つけてみると便利だと思います。

N/nCols*Sh + nCols*Sw

いずれかがうまくいくとしたら、Dunnoですが、仕事の開始を5分遅らせることができるので、致命的な損失にはなりません。

于 2008-12-04T09:12:03.433 に答える
0

長方形の数に制限がない場合は、SwとShのLCD(最小公分母)を見つける必要があります。次に、それをSwとShで割って、水平方向と垂直方向のカウントを見つけることができます。

限られているので違います。すべての長方形を使い切る必要があり、結果も長方形でなければならないことを正しく理解していますか?そうだと思います。

このような場合、長方形の配置方法については、それほど多くの選択肢がありません。一緒に乗算されたときにNを与える整数ペアはその数だけあります。

あなたの場合、私はそのような整数の可能なすべてのペアを見つけて(単純なFORループを使用して)、どれが正方形に最も近いかを確認しようとします。FORループの通知では、sqrt(N)までしかチェックする必要がないことに注意してください。これは、その後に見つかるすべての整数ペアが、逆に、すでに見つけたものと同じになるためです。

于 2008-12-04T09:03:02.077 に答える
0

まず、特殊な場合の真正方形の長方形または寸法がゼロの長方形。

それ以外の場合は、説明を簡単にするために、繰り返しビルドします。

    高さが幅より大きくなるまで新しい行を追加する
    幅が高さより大きくなるまで新しい列を追加する

コードでは次のようになります。

    // 最初のタイルを初期化として配置
    int タイル = num_tiles - 1;
    int 行 = 1;
    int 列 = 1;
    int 幅 = sx;
    int の高さ = sy;

    int i=1; // 何回反復したか知りたいからです

    // ほぼ正方形を構築します
    while(タイル > 0) {
        while((タイル > 0)
        && ((幅 + sx) <= (高さ + sy))) {
            // 列を追加
            タイル -= 行;
            列++;
            幅 += sx;
        i++;
        }
        while((タイル > 0)
        && ((高さ + sy) < (幅 + sx))) {
            // 行を追加
            タイル -= 列;
            行++;
            高さ += sy;
        i++;
        }
    }

    // 終わり
    printf("%d = %d (%dx%d) = %dx%d (%dx%d) in %d\n",
    num_tiles,tiles,sx,sy,rows,columns,width,height,i);

そしていくつかの結果:

100 = -5 (10x20) = 7x15 (150x140) in 21
1000 = -12 (10x20) = 22x46 (460x440) で 67
10000000 = -1628 (10x20) = 2236x4473 (44730x44720) で 6708
29 で 200 = 0 (7x13) = 10x20 (140x130)
2000 = -13 (7x13) = 93 で 33x61 (427x429)
20000000 = -3790 (7x13) = 3282x6095 (42665x42666) で 9376
400 = -14 (17x13) = 23x18 (306x299) で 40
4000 = -15 (17x13) = 73x55 (935x949) で 127
40000000 = -192 (17x13) = 7232x5531 (94027x94016) で 12762

非常に薄い長方形、または少数の長方形の場合、最悪の場合は O(n) です。しかし、一般的なケースでは O(sqrt(n)) ?

于 2008-12-04T09:44:56.830 に答える