Il s'agit d'un problème issu du tour de qualification du Google Code Jam (qui est maintenant terminé). Comment résoudre ce problème ?
Note : Si vous avez une méthode différente de celles présentées dans les réponses, veuillez la partager afin que nous puissions élargir nos connaissances sur les différentes façons de résoudre ce problème.
Minesweeper est un jeu d'ordinateur qui est devenu populaire dans les années 1980 et qui est toujours inclus dans certaines versions du système d'exploitation Microsoft Windows. Ce problème a une idée similaire, mais il ne suppose pas que vous ayez joué au Minesweeper.
Dans ce problème, vous jouez à un jeu sur une grille de cellules identiques. Le contenu de chaque cellule est initialement caché. Il y a M mines cachées dans M cellules différentes de la grille. Aucune autre cellule ne contient de mines. Vous pouvez cliquer sur n'importe quelle cellule pour la révéler. Si la cellule révélée contient une mine, le jeu est terminé et vous perdez. Sinon, la cellule révélée contiendra un chiffre compris entre 0 et 8 inclus, qui correspond au nombre de cellules voisines qui contiennent des mines. Deux cellules sont voisines si elles partagent un coin ou un bord. De plus, si la cellule révélée contient un 0, alors tous les voisins de la cellule révélée sont automatiquement révélés aussi, de manière récursive. Lorsque toutes les cellules qui ne contiennent pas de mines ont été révélées, le jeu se termine et vous gagnez.
Par exemple, une configuration initiale du tableau peut ressembler à ceci ('*' indique une mine, et 'c' est la première cellule cliquée) :
*..*...**.
....*.....
..c..*....
........*.
..........
Il n'y a pas de mines adjacentes à la cellule cliquée, donc lorsqu'elle est révélée, elle devient un 0, et ses 8 cellules adjacentes sont également révélées. Ce processus se poursuit, ce qui donne le tableau suivant :
*..*...**.
1112*.....
00012*....
00001111*.
00000001..
À ce stade, il y a encore des cellules non révélées qui ne contiennent pas de mines (indiquées par les caractères "."), le joueur doit donc cliquer à nouveau pour continuer le jeu.
Vous voulez gagner la partie le plus rapidement possible. Il n'y a rien de plus rapide que de gagner en un clic. Compte tenu de la taille du plateau (R x C) et du nombre de mines cachées M, est-il possible (bien que peu probable) de gagner en un seul clic ? Vous pouvez choisir où vous cliquez. Si c'est possible, imprimez toute configuration de mine valide et les coordonnées de votre clic, en suivant les spécifications de la section Sortie. Sinon, imprimez "Impossible".
Ma solution éprouvée :
Pour la solution, vous devez donc vous assurer que chaque nœud non miné se trouve dans une matrice 3x3 avec d'autres nœuds non minés, ou une matrice 3x2 ou 2x2 si le nœud se trouve sur un bord de la grille ; appelons cela une matrice 0. Ainsi, tout nœud dans une matrice 0Matrix a tous les voisins non mineurs.
Premièrement, vérifiez si moins de mines sont nécessaires, ou moins de nœuds vides.
if(# mines required < 1/3 of total grid size)
// Initialize the grid to all clear nodes and populate the mines
foreach (Node A : the set of non-mine nodes)
foreach (Node AN : A.neighbors)
if AN forms a OMatrix with it's neighbors, continue
else break;
// If we got here means we can make A a mine since all of it's neighbors
// form 0Matricies with their other neighbors
// End this loop when we've added the number of mines required
else
// We initialize the grid to all mines and populate the clear nodes
// Here I handle grids > 3x3;
// For smaller grids, I hard coded the logic, eg: 1xn grids, you just populate in 1 dimension
// Now we know that the # clear nodes required will be 3n+2 or 3n+4
// eg: if a 4x4 grid need 8 clear nodes : 3(2) + 2
For (1 -> num 3's needed)
Add 3 nodes going horizontally
When horizontal axis is filled, add 3 nodes going vertically
When vertical axis is filled, go back to horizontal then vertical and so on.
for(1 -> num 2's needed)
Add 2 nodes going horizontally or continuing in the direction from above
When horizontal axis is filled, add 2 nodes going vertically
Par exemple, si nous avons une grille de 4x4 nécessitant 8 nœuds propres, voici les étapes à suivre :
// Initial grid of all mines
* * * *
* * * *
* * * *
* * * *
// Populating 3's horizontally
. * * *
. * * *
. * * *
* * * *
. . * *
. . * *
. . * *
* * * *
// Populating 2's continuing in the same direction as 3's
. . . *
. . . *
. . * *
* * * *
Autre exemple : Grille 4x4 avec 11 nœuds clairs nécessaires ; sortie :
. . . .
. . . .
. . . *
* * * *
Autre exemple : Grille 4x4 avec 14 nœuds clairs nécessaires ; sortie :
// Insert the 4 3's horizontally, then switch to vertical to insert the 2's
. . . .
. . . .
. . . .
. . * *
Nous avons maintenant une grille qui est entièrement remplie et qui peut être résolue en un clic si nous cliquons sur (0, 0).
Ma solution fonctionne pour la plupart des cas, mais elle n'a pas passé la soumission (j'ai vérifié un fichier de sortie entier de 225 cas), donc je suppose qu'elle a quelques problèmes, et je suis presque sûr qu'il y a de meilleures solutions.