2D配列で形状を検索し、最適化する


11

画像が許可されました。下のゲームの画像は、「T」字型の一部として認識されている、いくつかの暗いブロックを示しています。ご覧のように、コードは赤い点でブロックを暗くしており、緑色の輪郭を持つ "T"形状は見ていません。

望ましいパターンが見つかりましたが、まだ最適化されていません

私のコードは、x / yをループし、ブロックを使用済みとしてマークし、形状を回転させ、繰り返し、色を変更し、繰り返します。

私はこのチェックを大きな不安で修正しようと試み始めました。現在のアイデアは:

  • グリッドをループしてすべてのパターンオカレンス(使用済みとしてブロックをマークしない)をメモし、これらを配列に書き込みます
  • もう一度グリッドをループします。今度は、どのブロックがどのパターンで占められているか、したがって、どのブロックが複数のパターンで占められているかに注目します。
  • もう一度グリッドをループします。今回は、どのパターンがどのパターンを妨げているかに注目します

それだけでいいと思います。

私はしなければならないと思う

  • 最初に他のほとんどのパターンを妨害するものから始めて、矛盾する形状のさまざまな組み合わせを試してください。これにどのようにアプローチしますか?
  • 8つのブロックを占有する3つの競合する形状があり、形状はそれぞれ4ブロックであるため、最大2つの形状しか持てないという有理数を使用します。

(私は他の形状も組み込むつもりであり、競合する形状を通過するときに考慮する必要があるスコアの重み付けがおそらくありますが、それは別の日になる可能性があります)

箱詰めの問題ではないと思いますが、何を調べればよいかわかりません。あなたの助けに感謝して、それが理にかなっていると思います

編集質問の明快さにもかかわらず、誰もが理解しているようです、はい、

各色の中で最大の「T」字を見つけたい

(もし私があなたに2つのポイントを与えて、あなたが3つを作ったなら、あなたは少しイライラするでしょう)


貪欲なアルゴリズムは、ボードを結合されたブロックのコレクションに分割することです。次に、各コレクションについて、図形で塗りつぶしてみて、暗くならない残りのブロックの数に応じてスコアにスコアを付けます。一種の私はen.wikipedia.org/wiki/Knapsack_problemを思い起こさせます。
ジョナサンコネル

2
質問に欠けているものがあると思います。できるだけ多くの「T」字型グループを見つけるアルゴリズムを作成しますか?
Markus von Broady、2012年

私があなたを理解していれば、あなたは正しい方向に進んでいます。あなたはあまり明確ではないので、詳しく説明していただければ幸いです。
AturSams

回答:


3

赤くマークされたブロックが正しいかどうかを見てみましょう。赤のブロックは青で、アルゴリズムはT形を見つけて赤のマークを付けましたが、正しいですか?あなたの目標は、同じ色のブロックでできるだけ多くのT形を見つけることです。現在、それらを見つけたら、それらをマークアウトし、アルゴリズムの有用性を低下させます(最適なソリューションが見つからない可能性があるため)。すべての形状を検索し、使用するものと使用しないものを選択することを計画しています。これまでのところ正しいですか?アルゴリズムが完了したときに、Tシェイプ内に含まれるブロックの量を最大化したい場合。

私が正しければ、以下はあなたの状況に最適な解決策だと思います。

整数線形計画法を使用します。

私は過去にこれを使用したと思います:

http://sourceforge.net/projects/lpsolve/

http://lpsolve.sourceforge.net/5.5/Java/README.html

(あなたはそれを多くの言語で動作させることができます、私はそれをPHP、Java、Cで使用しました)

ボード上で可能なすべてのTシェイプを登録し、ILPを使用してカバーされるブロックの量を最大化します。ILPは指数関数的に複雑です。ボードのサイズを考慮すると、それは問題にはなりません。私はILPを使用したグラフではるかに複雑な最小/最大の質問を実行しましたが、完了するまでに数分の1秒しかかかりませんでした。数百の頂点を使用した場合、最大30〜90秒でした(あなたの場合、それは数分の1秒に該当します)。

私がお勧めすること:

  1. 可能なすべてのライン形状を見つける
  2. 同じ色のライン形状間のすべての交点を見つける
  3. すべての交差点を検索して、可能なすべてのT形状を見つけます。
  4. 各T形状の線形問題でブール変数を定義します(0 <= Bi <= 1)値は整数であるため、0または1のままになります。
  5. 交差するT形状の各カップルの条件を作成します(Bi + Bj <= 1
  6. 目的関数は( "T"形状のブロックの合計(i)* Bi)
  7. ソルバーを実行し、ソルバーの対応するブール値が1であるT形状を、最適解で1に暗くします。

これは貴重な知識です。私は作業プロジェクトに線形ソルバーをよく使用しました。

ILPは基本的に、ある線形関数の最大値または最小値を達成したい場合の選択問題を解決する方法です。

あなたはここでもっと読むことができます、整数線形プログラミングの使用と線形プログラミングはプログラマにとって同じですが、コンピュータにとって整数ははるかに複雑であり、実行時間が長くなる可能性があります。あなたのケースではありません、それは非常にシンプルで、最悪の場合でもミリ秒未満しかかかりません。

ここでもっと読むことができると思います:

http://en.wikipedia.org/wiki/Integer_linear_programming#Integer_unknowns

これはそれをうまく説明しています:

http://fisher.osu.edu/~croxton_4/tutorial/

それは基本的に意思決定問題ソルバーであり、あなたが望む結果を最大化する決定をする方法です。これは、結果を判断する関数が特定の現在のケースでは線形であると想定しています。この場合の結果を判断する関数は、暗くすることを決定したすべてのT形状のブロックを合計します。

数学的には、変数を設定する方法:現在のケースでは、ブール値(インデックスiでTシェイプを暗くしたかどうか)を最適な値に設定して、必要な結果を最大化します:交差するTシェイプを暗くせずに、できるだけ多くのブロックを暗くします。必要な結果が線形関数で計算できる限り、すべての変数が設定されていれば解決できます。この例では、暗くしたT形をチェックし、それらがカバーするブロックを合計します。

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

これは些細なことではないことを知っているので、もしあなたが飛躍することを選んだら、気軽にコメントしてください、そして私は詳しく説明します。


アーサー、助けてくれてありがとう。ダイジェストするには、数回の読み取りが必要な場合があります。そして、はい、あなたは問題を正しく理解しました。詳細を教えていただければ非常に興味があります(いや、それは簡単なことではありません)。
アセンブラ、

実装にどの言語を使用していますか?
AturSams 2012年

アクションスクリプト3!みんなのお気に入り!
アセンブラ、

こっちも一緒。as3で実装を記述し、コメント付きでダウンロードするためにgithubにアップロードし、段階的に作業します
AturSams

コメントを追加したり、詳しく説明したりする特定の領域1〜7がありますか。ところで、AS3愛好家に朗報です。アドビはC ++をサポートするFlasCCをリリースしました。これにより、既存の線形ソルバーを簡単に使用できます。:)
AturSams 2012年

4

グリッドで発生するすべての(オーバーラップしている可能性がある)T形状のリストを取得したら、残されているのは最大集合パッキング問題です。

一般に、これはNP完全な問題です。ただし、グリッドは十分に小さいので(通常、さらに小さな独立したサブ問題に分割されます)、正確なソリューションを取得することは十分に可能です。


補遺:これは、トリックを実行する可能性のある基本的なバックトラッキング検索アルゴリズムです。

function max_packing_recursive ( set A, set S, set M ):
    if |M| < |S| then let M = S;
    for each shape X in A do:
        remove X from A;
        let B = A;
        remove all shapes that intersect with X from B;
        if |M| < |B| + |S| + 1 then:        // upper bound
            let M = max_packing_recursive( B, S + {X}, M );
        end if
        if |M| >= |A| + |S| then return M;  // shortcut
    end for
    return M;
end function

function max_packing( set A ):
    return max_packing_recursive( A, {}, {} );
end function

ここで、{X, Y, Z}は要素を含むセットを示しXYおよびZ{}空のセットである)、セット|Q|のサイズを示しQます。

再帰関数では、セットAには、残りのソリューションで使用可能なS形状が含まれ、現在のソリューション候補の形状が含まれ、Mこれまでの最大のソリューションです(これを返すのではなく、グローバル変数として保存することをお勧めします)。呼び出しチェーン)。重要な最適化は// upper bound、でマークされた行にありMます。これは、より優れたソリューションを返すことができない検索ツリーの枝を枝刈りします。

(実際には、我々は、各T字形は正確に4部位を含んでいることを知っているので、はるかに優れた上部置き換えることによって得られた結合|B|で形状によって覆わ異なる部位の数とBについても同様に4分割、および切り捨て(及び|A|上でマークされた行// shortcut)ただし、上記のアルゴリズムは、形状の任意のコレクションに対して機能します。)

上記で実装していない可能性のある追加の最適化は、A異なるサブセットの形状が重複していないという意味で、独立した複数のサブセットに分割するかどうかを再帰関数の先頭でチェックすることです。それぞれのサブセットに対するアルゴリズムを個別に。(いずれの場合でも、再帰アルゴリズムを呼び出す前に、必ずこれを最上位レベルで1回実行することをお勧めします。)形状をAループする前に、形状を適切に並べ替えます。。


ええ、問題のサイズのため、彼はILPを使用して比較的簡単に問題を解決できると思います.. 2 ^ 20〜= 1,000,000なので、T形状が非常に多くなる可能性があるため、このために線形ソルバーを使用して問題ない。これは明らかに指数関数的に複雑です(少なくとも誰かがp = npであることを証明するまで)。このサイズにより、この比較的単純なケースでヒューリスティックを回避できます。
AturSams

イルマリさん、どうもありがとうございました。この答えも、理解するのに少しはかかります。任意形状ビットは、将来の反復で役立つ可能性があります。
アセンブラ、
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.