web-dev-qa-db-fra.com

Algorithme pour trouver le moins de rectangles pour couvrir un ensemble de rectangles sans se chevaucher

J'ai un ensemble de rectangles et je voudrais "réduire" l'ensemble afin d'avoir le moins de rectangles pour décrire la même zone que l'ensemble d'origine. Si possible, je voudrais que ce soit aussi rapide, mais je suis plus soucieux de réduire le plus possible le nombre de rectangles. J'ai maintenant une approche qui fonctionne la plupart du temps.

Actuellement, je commence par le rectangle le plus en haut à gauche et je vois si je peux le développer à droite et en bas tout en le conservant comme un rectangle. Je le fais jusqu'à ce qu'il ne puisse plus se développer, supprimer et diviser tous les rectangles qui se croisent et ajouter le rectangle développé dans la liste. Ensuite, je recommence le processus avec le rectangle le plus en haut à gauche suivant, et ainsi de suite. Mais dans certains cas, cela ne fonctionne pas. Par exemple: enter image description here

Avec cet ensemble de trois rectangles, la bonne solution se retrouverait avec deux rectangles, comme ceci: enter image description here

Cependant, dans ce cas, mon algorithme commence par traiter le rectangle bleu. Cela se développe vers le bas et divise le rectangle jaune (correctement). Mais ensuite, lorsque le reste du rectangle jaune est traité, au lieu de s'étendre vers le bas, il se développe d'abord à droite et reprend la partie qui était auparavant séparée. Ensuite, le dernier rectangle est traité et il ne peut pas se développer vers la droite ou vers le bas, de sorte que l'ensemble de rectangles d'origine est laissé. Je pourrais modifier l'algorithme pour développer d'abord vers le bas puis vers la droite. Cela résoudrait ce cas, mais cela provoquerait le même problème dans un scénario similaire qui a été inversé.

Edit: Juste pour clarifier, l'ensemble original de rectangles ne se chevauchent pas et n'ont pas besoin d'être connectés. Et si un sous-ensemble de rectangles est connecté, le polygone qui les recouvre complètement peut avoir des trous.

69
Mike Dour

Malgré le titre de votre question, je pense que vous cherchez en fait la dissection minimale en rectangles d'un polygone rectiligne. (Les liens de Jason concernent les couvertures minimales par rectangles, ce qui est un problème assez différent.)

David Eppstein discute de ce problème dans la section 3 de son article d'enquête de 2010 Graph-Theoretic Solutions to Computational Geometry Problems , et il donne un joli résumé en cette réponse sur mathoverflow.net :

L'idée est de trouver le nombre maximum de diagonales axe-parallèle disjointes qui ont deux sommets concaves comme extrémités, divisées le long de celles-ci, puis forment une autre division pour chaque sommet concave restant. Pour trouver le nombre maximal de diagonales à axes parallèles disjoints, formez le graphique d'intersection des diagonales; ce graphe étant bipartite, son ensemble indépendant maximum peut être trouvé en temps polynomial par des techniques de correspondance de graphe.

Voici mon gloss sur cette description admirablement concise, en utilisant la figure 2 de l'article d'Eppstein. Supposons que nous ayons un polygone rectiligne, éventuellement avec des trous.

Lorsque le polygone est disséqué en rectangles, chacun des sommets concaves doit être rencontré par au moins un bord de la dissection. Nous obtenons donc la dissection minimale si autant de ces arêtes que possible font un double usage, c'est-à-dire qu'elles relient deux des sommets concaves.

Alors dessinons les diagonales axe-parallèle entre deux sommets concaves qui sont entièrement contenus dans le polygone. ('Axe-parallèle' signifie ici 'horizontal ou vertical', et une diagonale d'un polygone est une ligne reliant deux sommets non adjacents.) Nous voulons utiliser autant de ces lignes que possible dans la dissection tant qu'ils ne se coupent pas.

(S'il n'y a pas de diagonales parallèles à l'axe, la dissection est triviale - il suffit de faire une coupe à partir de chaque sommet concave. Ou s'il n'y a pas d'intersections entre les diagonales à axe parallèle, nous les utilisons toutes, plus une coupe de chaque sommet concave restant . Sinon, lisez la suite.)

Le graphique d'intersection d'un ensemble de segments de ligne a un nœud pour chaque segment de ligne, et un bord rejoint deux nœuds si les lignes se croisent. Voici le graphique d'intersection pour les diagonales axe-parallèle:

C'est bipartite avec les diagonales verticales dans une partie et les diagonales horizontales dans l'autre partie. Maintenant, nous voulons choisir autant de diagonales que possible tant qu'elles ne se croisent pas. Cela correspond à trouver le ensemble indépendant maximum dans le graphe d'intersection.

Trouver l'ensemble indépendant maximum dans un graphe général est un problème NP-difficile, mais dans le cas spécial d'un graphe bipartite, le théorème de König montre qu'il est équivalent au problème de trouver une correspondance maximale, qui peut être résolu en temps polynomial, par exemple par algorithme de Hopcroft – Karp . Un graphique donné peut avoir plusieurs correspondances maximales, mais chacune d'elles fera l'affaire, car elles ont toutes la même taille. Dans l'exemple, toutes les correspondances maximales ont trois paires de sommets, par exemple {(2, 4), (6, 3), (7, 8)}:

(Les autres correspondances maximales dans ce graphique incluent {(1, 3), (2, 5), (7, 8)}; {(2, 4), (3, 6), (5, 7)}; et { (1, 3), (2, 4), (7, 8)}.)

Pour obtenir une correspondance maximale avec la correspondance couverture minimale des sommets , appliquez la preuve du théorème de König . Dans la correspondance ci-dessus, l'ensemble de gauche est [~ # ~] l [~ # ~] = {1, 2, 6, 7}, l'ensemble de droite est [~ # ~] r [~ # ~] = {3, 4, 5, 8}, et l'ensemble des sommets sans correspondance dans [~ # ~] l [~ # ~] est [~ # ~] u [~ # ~ ] = {1}. Il n'y a qu'un seul chemin alternatif commençant par [~ # ~] u [~ # ~] , à savoir 1–3–6, donc l'ensemble des sommets dans les chemins alternés est [~ # ~] z [~ # ~] = {1, 3, 6} et la couverture minimale des sommets est donc [~ # ~] k [~ # ~] = ( [~ # ~] l [~ # ~] \ [~ # ~] z [~ # ~] ) ∪ ( [~ # ~] r [~ # ~] [~ # ~] z [~ # ~] ) = {2, 3, 7}, indiqué en rouge ci-dessous, avec le maximum indépendant défini en vert:

Traduisant cela en arrière dans le problème de dissection, cela signifie que nous pouvons utiliser cinq diagonales parallèles à l'axe dans la dissection:

Enfin, faites une coupe de chaque sommet concave restant pour terminer la dissection:

118
Gareth Rees

Voici quelques articles universitaires discutant des solutions à ce problème;

n algorithme d'approximation de temps linéaire pour une couverture rectangulaire minimale (c'est pour couvrir des polygones, c'est donc un cas plus général que ce que vous avez présenté ici).

Couvertures rectangulaires optimales pour les polygones rectilignes convexes (celui-ci correspond davantage à votre problème spécifique)

Vous pouvez également essayer ici pour une bibliographie de plus d'articles sur ce sujet.

8
Jason Moore