假设函数将s
(原点六边形),f
(目标六边形)和n
(路径长度)值作为参数并输出所有可能路径的列表有n长度。要想象出问题,请查看下图:
让我们说我们的起源(s
)是红色虚线十六进制(2, 3)
,目标(f
)是蓝色虚线(5, 2)
。我们希望以5个步骤(n = 5
)到达蓝色虚线十六进制。还要考虑如果步行到达特定的十六进制,它也可能在下一步中保留在该十六进制中。换句话说,其中一条可能的路径可以是(3, 2) - (4, 2) - (5, 2) - (5, 2) - (5, 2)
。它也算作5长度路径。
这些是从(2, 3)
到(5, 2)
的一些示例路径:
(1, 3) - (2, 3) - (3, 2) - (4, 3) - (5, 2)
(3, 3) - (4, 4) - (5, 4) - (5, 3) - (5, 2)
(2, 3) - (2, 3) - (3, 3) - (4, 3) - (5, 2)
我希望以某种方式找到所有这些路径。但是,我无法确定哪种算法能够提供最有效的解决方案来解决此问题。首先想到的是使用深度优先搜索,但我想知道在这种情况下是否有更好的选择。
答案 0 :(得分:1)
假设您定义了以下递归函数,返回对列表的列表,其中每个对列表是从from
到to
的长度为i
的路径:
find_paths_from_to_with_length(from, to, i):
if i == 1:
if to in neighbors(from) or from == to:
return [[(from, to)]]
return []
all_paths = []
for node in neighbors(from) + [from]:
neighbor_all_paths = find_paths_from_to_with_length(node, to, i - 1)
for path in neigbor_all_paths:
all_paths.append([(from, node)] + neighbor_path
return all_paths
然后你只需要用你的来源,目标和所需的长度来调用它。
答案 1 :(得分:1)
对于像这样的十六进制网格,
两个节点之间的曼哈顿距离可以通过使用:
来计算function dist = manhattan_dist( p, q )
y1 = p(1);
y2 = q(1);
x1 = p(2);
x2 = q(2);
du = x2 - x1;
dv = (y2 - floor(x2 / 2)) - (y1 - floor(x1 / 2));
if ((du >= 0 && dv >= 0) || (du < 0 && dv < 0))
dist = abs(du) + abs(dv);
else
dist = max(abs(du), abs(dv));
end
end
以前在这些问题中已经讨论过这个问题:
我相信我们可以通过将其与manhattan_dist
:
function all_paths = find_paths( from, to, i )
if i == 1
all_paths = to;
return;
end
all_paths = [];
neighbors = neighbor_nodes(from, 8);
for j = 1:length(neighbors)
if manhattan_dist(neighbors(j,:), to) <= i - 1
paths = find_paths(neighbors(j,:), to, i - 1);
for k = 1:size(paths, 1)
all_paths = [all_paths; {neighbors(j,:)} paths(k,:)];
end
end
end
end
最后,如您所见,有一个辅助函数来获取邻居节点的索引:
function neighbors = neighbor_nodes( node, n )
y = node(1);
x = node(2);
neighbors = [];
neighbors = [neighbors; [y, x]];
if mod(x,2) == 1
neighbors = [neighbors; [y, x-1]];
if y > 0
neighbors = [neighbors; [y-1, x]];
end
if x < n - 1
neighbors = [neighbors; [y, x+1]];
neighbors = [neighbors; [y+1, x+1]];
end
neighbors = [neighbors; [y+1, x-1]];
if y < n - 1
neighbors = [neighbors; [y+1, x]];
end
else
if y > 0
neighbors = [neighbors; [y-1, x]];
neighbors = [neighbors; [y-1, x+1]];
if x > 0
neighbors = [neighbors; [y-1, x-1]];
end
end
if y < n
neighbors = [neighbors; [y+1, x]];
neighbors = [neighbors; [y, x+1]];
if x > 0
neighbors = [neighbors; [y, x-1]];
end
end
end
end
如果节点与目标节点的曼哈顿距离大于当前递归调用的长度n
,则主要思想就是修剪节点。举例来说,如果我们可以分两步((1, 1)
)从(0, 3)
转到n = 2
,则应修剪除(1, 2)
以外的所有邻居节点。