タイルセットの境界の効率的なアルゴリズム
この投稿を改善したいですか?引用や回答が正しい理由の説明など、この質問に対する詳細な回答を提供します。十分な詳細がない回答は、編集または削除できます。 地図を形成する既知の有限サイズのタイルのグリッドがあります。マップ内の一部のタイルは、テリトリーと呼ばれるセットに配置されます。この領域はつながっていますが、その形状については何もわかっていません。ほとんどの場合、それはかなり規則的なブロブになりますが、一方向に非常に長くなる可能性があり、潜在的に穴がある可能性もあります。領土の(外側の)境界を見つけることに興味があります。 つまり、テリトリー内に存在することなく、テリトリー内のタイルのいずれかに触れるすべてのタイルのリストが必要です。これを見つける効率的な方法は何ですか? 難易度を上げるために、タイルがヘックスであることが起こりますが、これはそれほど大きな違いをもたらさないと思われます。各タイルにはまだ整数のxおよびy座標がラベル付けされており、タイルがあれば、隣接するタイルを簡単に見つけることができます。以下にいくつかの例を示します。黒は領土、青は探したい境界線です。 これ自体は難しい問題ではありません。擬似Pythonのこのための簡単なアルゴリズムの1つは次のとおりです。 def find_border_of_territory(territory): border = [] for tile in territory: for neighbor in tile.neighbors(): if neighbor not in territory and neighbor not in border: border.add(neighbor) しかし、これは遅いので、もっと良いものが欲しいです。テリトリーでO(n)ループがあり、すべてのネイバーで別のループ(短いループですが、それでも)があります。次に、サイズがnである2つのリストのメンバーシップをチェックする必要があります。それはO(n ^ 2)のひどいスケーリングを与えます。ボーダーとテリトリーのリストの代わりにセットを使用して、メンバーシップをすばやくチェックできるようにすることで、それをO(n)に減らすことができますが、それでも素晴らしいことではありません。テリトリーは大きいが、単純な面積対線のスケーリングのために境界が小さい多くの場合があると予想しています。たとえば、領土が半径5のヘクスの場合、サイズは91ですが、境界線のサイズは36のみです。 誰かがもっと良いものを提案できますか? 編集: 以下の質問のいくつかに答えるため。領域のサイズは、約20〜100程度です。テリトリーを形成するタイルのセットはオブジェクトの属性であり、すべてのボーダータイルのセットを必要とするのはこのオブジェクトです。 最初、テリトリーはブロックとして作成され、その後、ほとんどの場合タイルが1つずつ増えます。この場合、最速の方法は、境界線のセットを保持し、取得したタイル上でのみ更新することです。領土に大きな変更が発生する場合があります-そのため、完全に再計算する必要があります。 私は、単純な境界検出アルゴリズムを実行することが最善の解決策であると考えています。これにより発生する唯一の追加の複雑性は、境界線が必要になるたびに再計算されるようにすることですが、それ以上ではありません。私は現在のフレームワークでこれを確実に行うことができると確信しています。 タイミングに関しては、現在のコードには、領土のすべてのタイルをチェックする必要があるいくつかのルーチンがあります。毎ターンではありませんが、作成時とその後は時々です。完全なプログラムのごく一部であるにもかかわらず、テストコードの私のスーツの実行時間の50%以上がかかります。したがって、繰り返しを最小限に抑えることに熱心でした。ただし、テストコードには、プログラムの通常の実行(当然)よりも多くのオブジェクトの作成が含まれるので、これはあまり重要ではないことがわかります。