我有一个网格,用于保存值为1和0的单元格(它们是随机生成的(。值为1的单元格表示它是一个空单元格,我可以移动到该单元格,值为0表示该单元格被阻止。我希望每个位置(x,y(都能通过向所有4个方向移动而不是对角移动来判断是否有到点(x',y'(的可用路径。
从一项研究来看,我的问题的解决方案是BFS算法,但我很难理解我们如何将数组转换为图,以及我们如何保留阻塞单元格的信息。
BFS的一般结构如下:
- 创建一个队列
- 登记根节点
- 虽然队列不是空的,
- 取消节点的队列
- 访问节点
- 将节点的子节点排队
此处应用
- 创建一个队列
- 创建
visited
,一个每个单元都有一个位的数组 - 对于每一行CCD_ 2,
- 对于每个列CCD_ 3,
- 如果小区(
x
、y
(具有值1
,- 设置单元(
x
、y
(的visited
位
- 设置单元(
- 否则,
- 清除单元(
x
、y
(的visited
位
- 清除单元(
- 如果小区(
- 对于每个列CCD_ 3,
- 将点(x,y(排队
- 虽然队列不是空的,
- 对点(
x2
、y2
(进行排队 - 如果没有设置用于小区的
visited
比特(x2
、y2
(,- 设置单元(
x2
、y
0(的visited
位 - 如果点(
x2
,y2
(等于(x’,y’(,- 返回true
- 对于与小区(
x2
、y2
(相邻的每个小区,- 对该单元格的坐标进行排队
- 设置单元(
- 对点(
- 返回false
(它不一定是位数组。它只需要提供快速查找和插入。例如,可以使用某种形式的关联数组。位向量似乎最适合我。(
但这并不完全正确。你不想简单地检查两个单元格是否连接,你想知道哪个单元格连接到哪个单元格。对每个单元格组合执行上述搜索将非常缓慢。以下内容可避免重复工作:
- 创建一个队列
- 创建
groups
,一个数组,每个单元格都有一个整数
该整数必须足够大,可以容纳单元格数加2。VOID
表示该整数可以取的最大值TODO
是指该整数可以取的最大值,减去1 - 对于每一行CCD_ 28,
- 对于每个列CCD_ 29,
- 如果小区(
x
0、y
(具有值1
,- 将
groups
中单元格(x
、y
(的整数设置为TODO
- 将
- 否则,
- 将
groups
中单元格(x
、y
(的整数设置为VOID
- 将
- 如果小区(
- 对于每个列CCD_ 29,
- 将
group_id
设置为0
- 对于每一行CCD_ 43,
- 对于每个列CCD_ 44,如果小区(
x
、y
(的组是TODO
,- 对点(
x
、y
(进行排队。- 当队列不是空的时,
- 出列点(
x2
、y2
( - 如果小区(
x2
、y2
(的组是TODO
,- 将单元(
x2
、y2
(的组设置为group_id
- 对于与小区(
x2
、y2
(相邻的每个小区,- 对该单元格的坐标进行排队
- 将单元(
- 出列点(
- 当队列不是空的时,
- 递增
group_id
- 对点(
- 对于每个列CCD_ 44,如果小区(
执行此操作后,每个单元格都将连接到groups
中具有相同值的其他单元格。
(同样,使用的确切数据结构具有灵活性。(
下面是一个示例实现。和上面一样,它仍然不在C中。重点是解释一种可以使用的方法,但实际的C实现留给用户。
输入:
use POSIX qw( ceil );
my $num_rows = ...;
my $num_cols = ...;
my $n = $y * $num_cols + $x;
my $cells = "