在过去尝试解决类似的问题时(主要是为了解决某些逻辑谜题),我总是发现最简单的方法是保留一堆你仍然需要查看的点,然后逐个处理它们直到堆栈为空。
groups = []
while any_points_left(A):
group = []
stack = [pick_random_point(A)]
while not_empty(stack):
p = stack.pop()
group.append(p)
mark_as_done(p)
for q in all_points_in_same_row_or_column(p):
stack.append(q)
groups.append(group)
翻译成Matlab(这不是这种代码的理想语言):
groups = {};
while nnz(A) > 0 % any points left?
% find random point
[i, j] = ind2sub(size(A), find(A, 1, 'first'));
stack = {[i, j]};
group = {};
while ~isempty(stack)
p = stack{end}; stack = stack(1:end-1); % pop point from stack
i = p(1); j = p(2);
if A(i, j) == 0 % check if point is not already removed
continue
end
A(i, j) = 0; % mark as done
group{end+1} = p; % add to group
for ii = 1:size(A, 1) % check same column
if A(ii, j) == 1
stack{end+1} = [ii, j]; % add to stack
end
end
for jj = 1:size(A, 2) % check same row
if A(i, jj) == 1
stack{end+1} = [i, jj]; % add to stack
end
end
end
groups{end+1} = group;
end
% print result
for ig = 1:length(groups)
fprintf('Group %i: ', ig)
group = groups{ig};
for ip = 1:length(group)
fprintf('(%i, %i) ', group{ip}(1), group{ip}(2))
end
fprintf('\n')
end
应该可以以清晰为代价将此代码编写得更紧凑。结果:
Group 1: (1, 1) (1, 4) (4, 4) (3, 4) (2, 1)
Group 2: (5, 2) (5, 3)