在图的隐式表示中查找连接的组件

时间:2013-12-03 02:14:47

标签: c++ algorithm graph

我在学校遇到CS问题,我似乎无法解决这个问题。

我们给出了一个字符串向量,它组成了一个“图像”。这个字符串向量有效地表示二维矩阵,并且在每个空格中,可以有4个字符中的一个:'K' - 骑士,'D' - 龙,'#' - 城堡墙,以及'' - 空的空间。

这个问题需要我们编写几个函数,例如:safe_knights - 它可以找到有多少骑士定位,龙无法移动到它们,castle_count(用于计算图像中的城堡)和knights_in_castles(用于计算骑士数量)住在城堡内。 (见下面的定义)

这项任务有些模糊,我很困惑从哪里开始。我提到的一个暗示是我们应该寻找空间的连通组件 - 如果我知道连接的是哪个空间,我就能确定龙是否有通往骑士的路径(safe_knights需要这个),或者城堡墙围绕着一个空间区域(将用于castle_count)。

我知道我可以使用其中一种图形遍历算法来帮助查找连接的组件,但我正在考虑如何实现它来处理在字符串向量中隐式表示的图形。这些碎片不是为了我而聚集在一起。

任何提示或想法指出我正确的方向将不胜感激!

//上述术语的定义:

城堡是由墙壁围绕的至少一个空间的区域。如果墙是正交的或在同一条线上而不是对角线,则连接墙。

Castles:                      ||   Not Castles:
####     ###    ######        ||   ##       ###     # 
#  #     # #    #    ####     ||   # #      # #     #
####     # #    #       #     ||   ###       #      ####  
         ###    #########     ||    

如果没有可以移动的龙,骑士是安全的。龙不能沿对角线移动。

Safe Knights:     ||     Tasty Knights:
###     ###       ||     #####         ###  D
#K# D   # K#      ||     #K  D#        # #  K
###     ###  D    ||     #####         #### 

示例问题以澄清我不理解的内容:

字符串向量称为图像。

假设(i,j)等同于(image [i])[j]处的字符(即图像[i]中字符串中的第j个字符。)

然后,我怎么看(i,j)并说“这是在城堡里”或“龙在(m,n)处可以到达这个空间”?

我是否需要某种跟踪,例如将已知连接组件存储为类的成员?

我假设每个点(i,j)都是图中的一个顶点,所以我想我需要一些方法来查看(i,j)并确定它与哪个顶点相邻。教师告诉我,我不需要单独表示图形(例如,扫描向量并构造邻接矩阵。)因此,我需要隐式操作图形而不是显式表示。

编辑: 所以,我更多地考虑了这一点,似乎每个函数的基础都将进行遍历,对于什么构成邻接的规定略有不同。例如:

safe_knights - 从骑士开始,DFS到法定空间,直到找到龙或者不再进行任何移动。法定空间是那些没有被墙壁或边缘挡住的主要方向。

castle_count - 从墙开始,DFS到包含墙的基本方向的空格,直到不能再进行此操作。我想我还需要一些方法来判断我是否一直回到我开始的地方 - 也许我记得那个函数中的起始节点。我可能还需要检查中间是否有空格。

knights_in_castles - 这个有点令人困惑 - 可能从每个骑士开始,检查他周围的空间直到找到一堵墙,然后检查那堵墙是否是城堡的一部分?

1 个答案:

答案 0 :(得分:1)

我猜您的问题是如何在对其应用普通图遍历算法之前使用关联矩阵(在每个单元格中存储边长)来表示棋盘。但实际上没有必要这样做。

通常在棋盘上,我们直接使用棋盘矩阵来表示这个问题,不需要在单元格中存储边长。如果我们想要找到连接的组件,我们使用深度优先搜索(DFS)或广度优先搜索(BFS)或A *搜索来查找它们。

递归DFS算法实现起来非常简单,但最初有点难以理解。

DFS(node v)
{
    visit(v);
    for each child w of v {
    // On a chessboard, they are right, left, up, and down neighbor cells
        DFS(w);
    }
}
  1. 在大多数情况下,我们使用全局标志矩阵来标记哪个单元格 被访问过。
  2. 在'visit(v)'之前,我们总是需要检查v是一个合法的单元格(通过检查坐标没有超出限制)。
  3. 例如,如果想要'safe_knights',我们先从骑士开始,DFS递归搜索邻居合法(不过界,不是墙)细胞,直到我们遇到龙,并快速返回。