Recherche de rectangles dans une grille à deux blocs
Disons que j'ai une grille de blocs, 7x12. Nous utilisons les couleurs '*','%','@' et une cellule vide '-'.
1 2 3 4 5 6 7
- - - - - - - 1
- - - - - - - 2
% % - - - - - 3
% % - - - - * 4
% % - - - @ % 5
@ @ @ - - @ % 6
@ @ * * * - * 7
* * * % % % % 8
% @ @ % * * % 9
% @ % % % % % 10
* * * % % @ @ 11
* * @ @ @ @ * 12
Je veux trouver des rectangles dans cette grille d'une certaine taille minimale, et le plus grand que je peux trouver, puis les plus petits jusqu'à ce qu'aucun des rectangles supérieure ou égale à la taille minimale peut être trouvé.
Dans cet exemple, considérez la taille minimale 1x4, 4x1, 2x2 donc un 1x3 n'est pas valide, mais une 2x3 est. Si nous voulons que le plus grand des rectangles, nous trouvons ce qui suit:
- 4x1 (4,8)
- 5x1 (3,10)
- 2x3 à (1,3)
- 2x2 (6,1)
- 2x2 (1,11)
- 4x1 (3,12)
Noter que les rectangles ne peut pas être dans l'espace, ils ne peuvent pas se chevaucher. Par exemple, la 2x2 rectangle (4,10) n'est pas mentionné car il recoupe le 5x1 rectangle (3,10).
Tous sont parfaitement valables rectangles: elles sont égales ou plus grandes que la taille minimum et tous les blocs par rectangle sont de la même couleur.
Ce que je veux, c'est de le faire par programmation. Lorsque vous dites à quelqu'un de trouver des rectangles dans une grille, il trouve tout de suite, sans réfléchir. La question est, comment puis-je écrire un algorithme qui fait la même chose?
J'ai considéré bruteforcing mais j'ai besoin de l'algorithme à exécuter aussi vite que possible car il devra être exécuté beaucoup dans un très petit laps de temps limité (mobile) de l'appareil.
Je vois beaucoup de questions sur l'internet au sujet des rectangles, mais je suis un peu surpris de cela il n'a pas été demandé partout. Je pense trop difficile ou n'a jamais voulu faire quelque chose comme cela?
source d'informationauteur Sebazzz
Vous devez vous connecter pour publier un commentaire.
Appeler la largeur et la hauteur de l'entrée de la matrice de W et H, respectivement.
Cette approche est "gourmand" dans la mesure où elle ne garantit pas de choisir la plus grande séquence de rectangles en général lorsqu'il y a plusieurs façons de se tailler une solide couleur de la région dans maximale des rectangles. (E. g. il pourrait être qu'il y a plusieurs rectangles dont l'angle supérieur gauche est à (10, 10) et qui ont une superficie de 16: 16x1, 8x2, en 4x4, en 2x8, 1x16. Dans ce cas, un choix peut produire de plus grosses rectangles "en aval", mais mon algorithme ne garantit pas à faire ce choix.) Si nécessaire, vous pouvez trouver l'ensemble optimal des séries de rectangles à l'aide de recul, bien que je soupçonne que cela pourrait être très lent dans le pire des cas.
La maximale du rectangle algorithme-je mentionner est conçu pour une seule couleur des rectangles, mais si vous ne pouvez pas s'adapter à votre multi-couleur de problème, vous pouvez simplement exécuter une fois pour chaque couleur avant de commencer l'étape 2.
J'ai eu à résoudre un problème très similaire pour mon tir à la première personne. - Je l'utiliser en entrée:
[ ][ ][ ][ ][ ][ ][ ][ ]
[ ][ ][ ][X][ ][ ][ ][ ]
[ ][X][X][X][X][X][X][X]
[ ][ ][X][X][X][X][ ][ ]
[ ][X][X][X][X][ ][ ][ ]
[ ][X][X][X][X][ ][ ][ ]
[ ][ ][X][ ][ ][ ][ ][ ]
[ ][ ][ ][ ][ ][ ][ ][ ]
Je reçois en sortie:
[ ][ ][ ][ ][ ][ ][ ][ ]
[ ][ ][ ][A][ ][ ][ ][ ]
[ ][B][G][G][G][F][E][E]
[ ][ ][G][G][G][F][ ][ ]
[ ][D][G][G][G][ ][ ][ ]
[ ][D][G][G][G][ ][ ][ ]
[ ][ ][C][ ][ ][ ][ ][ ]
[ ][ ][ ][ ][ ][ ][ ][ ]
Ce schéma est mieux. Le code source (sous Licence Publique Générale GNU version 2) est iciil est très bien commenté. Vous avez peut-être adapter un peu à vos besoins comme celle proposée par j_random_hacker.
Remarque: cela fonctionne sur l'hypothèse que vous essayez de trouver le plus grand
k
rectangles.Nous savons que nous devons, dans le pire des cas, regardez chaque nœud de la grille au moins une fois. Cela signifie que notre meilleur des cas pire-cast est
O(len*wid)
.Votre force brute va être
O(len*len*wid*wid)
avec l'approche naïve de "Vérification pour les rectangles en un point estO(len*wid)
et vous n'avez queO(len*wid)
fois.Il se peut que vous trouvez que cela n'est pas le cas, comme à chaque fois que vous trouvez un rectangle, vous avez un potentiel à réduire le problème de l'espace. Une approche par force brute de "vérifier chaque rectangle" je sens que va être la meilleure approche. Il y a des choses que vous pouvez faire pour l'accélérer.
Algorithme de base:
Garder une trace de la plus grande
k
rectangles. Comme vous allez le long, vous pouvez rechercher le périmètre de l'endroit où admissible rectangle peut être.Cela vous permet d'obtenir de gros gains de performance vers la fin de vos grosses recherches (si c'est une petite recherche, vous ne gagnez pas autant mais vous ne vous inquiétez pas parce que c'est une petite recherche!)
Également, cela ne fonctionne pas aussi bien pour les plus aléatoire distrobutions.
O(len*wid)
ce qui est un faible coût. Cela vous permettra de rechercher les zones les plus probables pour un grand rectangle.Notez qu'aucune de ces approches réduire le pire des cas. Mais, ils n'réduire le réel-monde s'attendait à temps de bon fonctionnement.
Ma propre solution est de trouver le plus grand rectangle, à l'aide de la même algorithme comme dans @j_random_hacker répondre, puis de diviser le reste de la surface en 4 régions, et de manière récursive recherche pour le plus grand rectangle de nouveau dans chacune de ces régions.
Lien vers les sources C++
Il aura moins de rectangles que l'on a accepté de répondre, parce que je trouve qu'il est difficile d'adopter cet algorithme pour enregistrer chaque intermédiaire rectangle lors de la recherche de la plus grande.
L'algorithme ignore tous les petits rectangles, de sorte que nous avons à parcourir chaque point de grille, afin de sauver chaque rectangle possible, puis jetez-les petits, et ce bosses de l'algorithme de retour à O(M3 ⋅ N3) complexité.
Nous pouvons diviser le reste de la surface, de deux manières, l'algorithme va vérifier à la fois, et d'utiliser l'option qui couvre la plupart de la zone, alors il va effectuer l'appel récursif à deux reprises, le temps de calculer la superficie, la deuxième fois pour remplir le tableau de sortie.
Nous pouvons laisser un seul choix de la zone de split à faire de l'algorithme de courir plus vite, parce que cette zone de comparaison ne donne pas beaucoup d'amélioration à la quantité de détection de rectangles, pour être honnête.
Edit: je viens de réaliser que de façon récursive de vérifier à la fois le fractionnement des variantes de pose, l'algorithme factorielle de la complexité, à quelque chose comme O(min(M,N)!). J'ai donc désactivé la deuxième zone de split, qui sort de l'algorithme avec une complexité O(M⋅N⋅log(M⋅N)).