这是来自 Google Code Jam 资格赛的问题(现在已经结束)。如何解决这个问题呢?
注意:如果您有与答案中讨论的方法不同的方法,请分享它,以便我们扩展我们对解决此问题的不同方法的了解。
Minesweeper 是一种在 1980 年代流行的电脑游戏,并且仍然包含在某些版本的 Microsoft Windows 操作系统中。这个问题有类似的想法,但它并不假设你玩过扫雷。
在这个问题中,你是在相同单元格的网格上玩游戏。每个单元格的内容最初是隐藏的。在网格的 M 个不同单元格中隐藏着 M 个地雷。没有其他细胞含有地雷。您可以单击任何单元格以显示它。如果显示的单元格包含地雷,则游戏结束,您输了。否则,显示的单元格将包含一个介于 0 和 8 之间的数字,包括 0 和 8,这对应于包含地雷的相邻单元格的数量。如果两个单元共享一个角或一个边,则它们是邻居。此外,如果显示单元格包含 0,则显示单元格的所有邻居也会自动递归显示。当所有不包含地雷的单元格都被揭露时,游戏结束,你赢了。
例如,板的初始配置可能如下所示('*' 表示地雷,'c' 是第一个单击的单元格):
*..*...**.
....*.....
..c..*....
........*.
..........
被点击的单元格附近没有地雷,所以当它被显示时,它变为0,并且它的8个相邻单元格也被显示出来。这个过程继续,产生以下板:
*..*...**.
1112*.....
00012*....
00001111*.
00000001..
此时,仍有未显示的不包含地雷的单元格(用“.”字符表示),因此玩家必须再次单击才能继续游戏。
你想尽快赢得比赛。没有什么比一键获胜更快的了。考虑到棋盘的大小(R x C)和隐藏地雷的数量 M,是否有可能(但不太可能)一键获胜?您可以选择单击的位置。如果可能,请按照输出部分中的说明打印任何有效的矿井配置和单击的坐标。否则,打印“不可能”。
我尝试过的解决方案:
因此对于解决方案,您需要确保每个非矿节点与其他非矿节点在一个 3x3 矩阵中,如果该节点位于网格的边缘,则为 3x2 或 2x2 矩阵;让我们称之为 0Matrix。所以 0Matrix 中的任何节点都有所有非我的邻居。
首先,检查是否需要更少的地雷,或者更少的空节点
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
例如,假设我们有一个需要 8 个干净节点的 4x4 网格,步骤如下:
// Initial grid of all mines
* * * *
* * * *
* * * *
* * * *
// Populating 3's horizontally
. * * *
. * * *
. * * *
* * * *
. . * *
. . * *
. . * *
* * * *
// Populating 2's continuing in the same direction as 3's
. . . *
. . . *
. . * *
* * * *
另一个例子:需要 11 个清晰节点的 4x4 网格;输出:
. . . .
. . . .
. . . *
* * * *
另一个例子:需要 14 个清晰节点的 4x4 网格;输出:
// Insert the 4 3's horizontally, then switch to vertical to insert the 2's
. . . .
. . . .
. . . .
. . * *
现在这里我们有一个完全填充的网格,如果我们单击 (0, 0),可以一键解决。
我的解决方案适用于大多数情况,但它没有通过提交(我确实检查了整个 225 个案例的输出文件),所以我猜它有一些问题,我很确定有更好的解决方案。