複数の長方形をより少ない数の長方形に「修復」するためのアルゴリズム?


13

ここに画像の説明を入力してください

さまざまな形と色の長方形のグリッドがあり、同じ色のレイアウトを表す長方形の数を減らしたい(最適に近いほど良い、最適である必要はない)とします。

上の画像は非常に単純化されたケースであり、長方形間の空白は視覚化のみを目的としています-実際には密に詰め込まれています。

これを行うのに役立つアプローチまたはアルゴリズム名(Googleに満足)とは何ですか?


3
これらの長方形がどこから来たかについて少し教えていただけますか?それらは、(大まかに)下にあるグリッドと整列する傾向がありますか、またはいくつかの共通のビルディングブロック、またはいくつかの最小の「原子」長方形を共有しますか?それらは回転できますか?これは、最も一般的なケースでは非常に厄介な種類の問題のように見えますが、特定のシナリオでいくつかの制約または共通点を活用できれば、はるかに簡単になる可能性があります。
DMGregory

(チェッカーボードのような)正方形の下にグリッドがあり、各長方形はそれらの下にある正方形と境界を共有しています。つまり、整数を使用して、すべての長方形の上部/下部/左/右を記述することができます。そのため、90度で割り切れない角度で回転させることはできません。また、NxMグリッドには四角形が完全に表示されます-覆われていないグリッドの位置はありません。
xaxxon

上記の例のように(配色の観点から)ケースを回避しようとしていますが、1x1の長方形のトンで構成されており、多くのスペースを処理できる場合は、それぞれを処理しています少ない呼び出し。
xaxxon

私はある種の「どこかから始めて、色の境界線に当たるまで1つの次元(垂直方向に言う)でどんどん大きな長方形を試し、次に境界線に当たるまで他の次元(水平方向)を拡大します。次に、最初に水平方向に試してください。 。。単純に3つの可能性上の最大の選択は正しいアプローチであれば、多分しかしないように注意してください(斜めに成長している)だけの正方形をしてみてください。
xaxxon

最終的に長方形が少なくなる場合、既存の長方形を分割することは許容されますか?または、アルゴリズムはマージするだけですか?また、合計数が唯一の基準ですか、それとも長い細いスライバーよりも正方形の形状を好むか、小さなものよりも大きな長方形を好みますか?
DMGregory

回答:


15

最初に、ソース長方形を下にあるグリッドのセルに変換して、入力をより均一にすることができます。(効果的に問題をラスタライズする)

これにより、ソースの四角形を直接操作する場合、特に複数のソースの四角形を分割してそれらを別の方法で再結合する場合に、明らかではない最適化を見つけることができます。

四角形をグリッドセルに変換して戻す例

次に、深さ優先探索アルゴリズムまたは塗りつぶしアルゴリズムを使用して、同じ色の接続された領域を見つけることができます。接続された各リージョン(ポリオミノ)を個別に検討できます。別のリージョンに対して行うことは、このリージョンに影響を与える必要はありません。

事実上、このポリオミノを長方形に分解する方法を見つけたいと思います(残念ながら、私が見つけることができるほとんどの文献は、反対の問題についてです:長方形をポリオミノに分解する!これにより、リードを検索するのが難しくなります...)

簡単な方法の1つは、隣接する正方形の水平方向のランを長い細長い長方形に結合することです。次に、上の行と比較して、実行の開始と終了が一致するかどうかを組み合わせることができます-各実行/行を終了するとき、または各セルを現在の実行に追加することを検討するとき。

ポリオミノを水平方向のランに分解してから垂直方向にマージする

この方法がどれほど最適になるかはまだわかりません。まだ考慮していない行が、これまでに見た行とは異なるスプリットを示唆している場合、少し問題が発生する可能性があります。

上記の方法で4が見つかる、3長方形の解の場合の例

ラン/長方形が上下のランで正確にカバーされていることを検出し、それを分割してマージすると、この特定のケースが解決されますが、問題がどれほど一般的であるかは調べていません。

また、ポリオミノの周囲を歩いて凹型のコーナーに遭遇するたびに横切る方法も調べましたが、この方法ではエラーが発生しやすくなります。最適な結果を得るには、2つの凹型コーナーを結合するカットに優先順位を付ける必要があり、くぼみを含む形状には特別な処理が必要であるため、行スキャン方式には単純さの利点があるようです。

私が検討しているもう1つの方法は、一番上の行にある最初の実行を取得して、できる限りそれを下に拡張することです。次に、残っている一番上の行を最初に実行します。ただし、これは逆T字型につまずくため、最適でもありません。

動的プログラミングを使用して最適な分割を見つける方法はおそらくあるように思いますが、まだそれを見つけていません。


素晴らしい答えをありがとう!その解決策は非常に高速に見えるので、いくつかの異なる方向に実行して、最もよく見える方向を選択することができます-水平方向の左→右、水平方向の右→左、次に垂直方向にも。
xaxxon

2
問題は、すべてのスイープ方向からアルゴリズムを誤解させる形状を構築できることです。それらは実際の使用では表示されない可能性がありますが、それでも私にはバグがあります。簡単な修正はまだあると思います...途中で凹型のコーナーがあるかどうか、各実行でメモするようなものです。次に、後続のランがまさにそのようなポイントで終了する場合、ランを垂直に分割する以上のランをバックトラックします。詳細はまだ整理していません。
DMGregory

1
また、なぜ洪水補充ステップが必要なのかわかりません。グリッドポジティノから細長い長方形に移動するときは、グリッドの行または列全体(どちらの方法でも)を歩くだけで、1xNの長方形を作成できます。ポリオミノを知る必要はありませんよね?
xaxxon

そうです、洪水充填は必要なステップではありません。以降の手順では、一度に1つの着色領域のみに焦点を当てることを正当化するためにそれを含めましたが、行走査方法を、交互配置された複数の着色領域に簡単に適用できます。ただし、境界線ベースの方法では、一度に1つの形状の境界線を処理する必要があります。
DMGregory
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.