Étant donné une image en noir et blanc avec un fond blanc et un ensemble de points noirs, peignez un ensemble de pixels blancs en rouge, de sorte qu'il y ait un chemin entre chaque paire de pixels noirs.
Détails
Un chemin est un ensemble de pixels connectés (connectivité à 8 quartiers). Les pixels noirs peuvent être utilisés dans le cadre des chemins. L'objectif est d'essayer de minimiser l'ensemble des pixels rouges dans les conditions ci-dessus et de produire une image correspondante.
Vous n'avez pas besoin de trouver la solution optimale.
Une solution triviale et en même temps la pire consiste à peindre tous les pixels blancs en rouge.
Exemple (les pixels sont agrandis pour la visibilité):
Détails
- Étant donné une image de pixel (dans tout format approprié), renvoyez une autre image avec les points connectés comme spécifié ci-dessus, ainsi qu'un entier indiquant le nombre de pixels rouges utilisés.
- Le score est le produit de (1 + le nombre de pixels rouges) pour chacun des 14 cas de test.
- L'objectif est d'avoir le score le plus bas.
Cas de test
Les 14 tests sont illustrés ci-dessous. Un programme python pour vérifier la connectivité des sorties peut être trouvé ici.
Meta
Merci à @Veskah, @Fatalize, @ wizzwizz4 et @trichoplax pour les différentes suggestions.
Réponses:
C, score 2,397 x 10 ^ 38
Mec, cela a pris trop de temps à faire, probablement à cause de mon choix de langue. J'ai fait fonctionner l'algorithme assez tôt, mais j'ai rencontré beaucoup de problèmes d'allocation de mémoire (impossible de récursivement libérer des trucs en raison de débordements de pile, les fuites étaient énormes).
Encore! Il bat l'autre entrée sur chaque cas de test, et
peut même être optimalse rapproche assez ou des solutions exactement optimales la plupart du temps.Quoi qu'il en soit, voici le code:
Testé sur: Arch Linux, GCC 9.1.0,
-O3
Ce code prend les entrées / sorties dans un fichier personnalisé que j'appelle "cppm" (car c'est comme une version condensée du format PPM classique). Un script python pour convertir vers / à partir de celui-ci est ci-dessous:
Explication de l'algorithme
Le fonctionnement de cet algorithme est qu'il commence par trouver toutes les formes connectées dans l'image, y compris les pixels rouges. Il prend ensuite le premier et étend sa frontière un pixel à la fois jusqu'à ce qu'il rencontre une autre forme. Il colore ensuite tous les pixels du toucher à la forme d'origine (en utilisant la liste de liens qu'il a créée en cours de route). Enfin, il répète le processus, trouvant toutes les nouvelles formes créées, jusqu'à ce qu'il ne reste qu'une forme.
Galerie d'images
Testcase 1, 183 pixelsTestcase 2, 140 pixels
Testcase 3, 244 pixels
Testcase 4, 42 pixels
Testcase 5, 622 pixels
Testcase 6, 1 pixel
Testcase 7, 104 pixels
Testcase 8, 2286 pixels
Testcase 9, 22 pixels
Testcase 10, 31581 pixels
Testcase 11, 21421 pixels
Testcase 12, 5465 pixels
Testcase 13, 4679 pixels
Testcase 14, 7362 pixels
la source
Python, 2,62 * 10 ^ 40
Cet algorithme remplit simplement (BFS) le plan à partir des parties noires de l'image, où pour chaque nouveau pixel, nous enregistrons la partie noire à partir de laquelle il a été inondé. Dès que nous avons deux pixels voisins avec des parties noires différentes comme ancêtres, nous fusionnons essentiellement ces deux parties noires en les joignant par les ancêtres des deux voisins que nous venons de trouver. En théorie, cela pourrait être implémenté dans
O(#pixels)
, mais pour maintenir la quantité de code à un niveau acceptable, cette implémentation est légèrement pire.Production
But
la source
Python 3:
1,7x10 ^ 421,5x10 ^ 41Utilisation
Pillow
,numpy
etscipy
.Les images sont supposées être dans un
images
dossier situé dans le même répertoire que le script.Avertissement : le traitement de toutes les images prend beaucoup de temps.
Code
Explication
Solution triviale. Nous commençons par changer la couleur de tous les pixels blancs d'une image en rouge. Ce faisant, il est garanti que tous les éléments (n'importe quelle île de pixels noirs) sont connectés.
Ensuite, nous parcourons tous les pixels de l'image en partant du coin supérieur gauche et en se déplaçant vers la droite et vers le bas. Pour chaque pixel rouge, nous constatons que nous changeons sa couleur en blanc. Si après ce changement de couleur il n'y a toujours qu'un seul élément (un élément étant maintenant n'importe quelle île de pixels noirs et rouges), nous laissons le pixel blanc et passons au pixel suivant. Cependant, si après le changement de couleur du rouge au blanc le nombre d'éléments est supérieur à un, nous laissons le pixel rouge et passons au pixel suivant.
Mise à jour
Comme il peut être vu (et attendu), les connexions obtenues en utilisant uniquement cette méthode montrent un motif régulier et dans certains cas, comme dans les images 6e et 11e, il y a des pixels rouges inutiles.
Ces pixels rouges supplémentaires peuvent être facilement supprimés en itérant à nouveau sur l'image et en effectuant les mêmes opérations que celles expliquées ci-dessus, mais du coin inférieur droit au coin supérieur gauche. Cette deuxième passe est beaucoup plus rapide car la quantité de pixels rouges à vérifier.
Résultats
Les images modifiées après le deuxième passage sont répertoriées deux fois pour montrer les différences.
Nombre de pixels rouges: 18825
Nombre de pixels rouges: 334
Nombre de pixels rouges: 1352
Nombre de pixels rouges: 20214
Nombre de pixels rouges: 47268
Nombre de pixels rouges:
6327Nombre de pixels rouges: 17889
Nombre de pixels rouges: 259
Nombre de pixels rouges: 6746
Nombre de pixels rouges: 586
Nombre de pixels rouges:
91Nombre de pixels rouges: 126
Nombre de pixels rouges: 212
Nombre de pixels rouges: 683
Calcul du score:
(1 + 6746) * (1 + 126) * (1 + 259) * (1 + 17889) * (1 + 334) * (1 + 586) * (1 + 18825) * (1 + 9) * (1 +683) * (1 + 1352) * (1 + 20214) * (1 + 212) * (1 + 63) * (1 + 47268) = 1778700054505858720992088713763655500800000 ~ 1,7x10 ^ 42
Mise à jour du calcul du score après l'ajout de la deuxième passe:
(1+ 18825) * (1+ 1352) * (1+ 20214) * (1+ 47268) * (1+ 27) * (1+ 17889) * (1+ 6746) * (1+ 586) * (1 + 1) * (1+ 126) * (1+ 212) * (1+ 334) * (1 + 259) * (1 + 683) = 155636254769262638086807762454319856320000 ~ 1,5x10 ^ 41
la source