迷茫童鞋的阅读指南
该项目的详细描述和算法的具体说明
请参见前一篇 Project2 Percolation in Grids 网格渗透
本人给出了percolation_provided.py的函数说明目前已完成水波探测算法的实现
该算法的关键是实现explore函数中递归,及percolation_recursive对explore的初始调用。
Step1:
国际惯例导入提供的函数:from percolation_provided import *
先考虑percolation_recursive函数,参数和前面的水波算法函数一样,定义为:percolation_recursive(input_grid, trace=True, short=False)
Step2:
老样子,还是生成一个flow_grid网格。
size = len(input_grid)
flow_grid = grid(size, -1)
flow_grid = grid(size, -1)
Step3:
为explore函数提供一个初始的开始状态,从第一行开始,遍历每个位置。
#start exploration from each space in top (zeroth) row
for col in range(size):
if explore(input_grid, flow_grid, 0, col, trace, short):
return flow_grid, True
for col in range(size):
if explore(input_grid, flow_grid, 0, col, trace, short):
return flow_grid, True
Step4:
设计这个explore函数,还是比较头疼的。关键是要考虑到如何在这里面实现递归,我们从项目中的描述来分解这个问题:
假设一个单元与[i][j]相邻,流能够到达(i也可以为第一行),input_grid[i][j]=0,flow_grid[i][j]=-1。这意味着没有流到达过[i][j]位置,该位置不阻塞,且流能够从相邻的位置到达它。我们通过设置flow_grid[i][j]=*来记录流能够到达位置[i][j]。然后,函数explore考虑流能够到达的[i][j]的相邻位置,每个位置探测一次。对于每个这样的相邻位置,explore将其相邻位置看作行列索引,并使用一次递归调用。在递归调用结束后,上面的explore的初始状态保持不变。
那么就是:
1.对于位置[i][j]的相邻位置,如果是开放且未被访问,使用递归调用
2.对于每次探索到的位置设置flow_grid[i][j]=*来标记,保证只探测一次
3.由percolation_recursive传来的值,需要判断该位置是否是开放的,是的话标记为'*'
4.算法是全部执行完才退出的,返回值为None,为了快速结束算法并确定是否渗透,我们使用传入的short布尔值变量作为判断,只要当前处理的位置处于最后一行,就退出返回True
具体实现如下:
def explore(input_grid, flow_grid, row, col, trace, short):
"""Explore the grid, marking unblocked cells as full as they are explored"""
size = len(input_grid)
if input_grid[row][col] == 0:
flow_grid[row][col] = '*'
if trace:
visualize(flow_grid, input_grid)
rate(2)
#explore neighboring cells
if short:
if row + 1 == size:
return True
# Look down
if row + 1 < size:
if input_grid[row+1][col] == 0 and flow_grid[row+1][col] == -1:
percolation_recursive_explore(input_grid, flow_grid,
row+1, col, trace, short)
# Look right
if col + 1 < size:
if input_grid[row][col+1] == 0 and flow_grid[row][col+1] == -1:
percolation_recursive_explore(input_grid, flow_grid,
row, col+1, trace, short)
# Look left
if col - 1 >= 0:
if input_grid[row][col-1] == 0 and flow_grid[row][col-1] == -1:
percolation_recursive_explore(input_grid, flow_grid,
row, col-1, trace, short)
# Look up
if row - 1 >= 0:
if input_grid[row-1][col] == 0 and flow_grid[row-1][col] == -1:
percolation_recursive_explore(input_grid, flow_grid,
row-1, col, trace, short)
"""Explore the grid, marking unblocked cells as full as they are explored"""
size = len(input_grid)
if input_grid[row][col] == 0:
flow_grid[row][col] = '*'
if trace:
visualize(flow_grid, input_grid)
rate(2)
#explore neighboring cells
if short:
if row + 1 == size:
return True
# Look down
if row + 1 < size:
if input_grid[row+1][col] == 0 and flow_grid[row+1][col] == -1:
percolation_recursive_explore(input_grid, flow_grid,
row+1, col, trace, short)
# Look right
if col + 1 < size:
if input_grid[row][col+1] == 0 and flow_grid[row][col+1] == -1:
percolation_recursive_explore(input_grid, flow_grid,
row, col+1, trace, short)
# Look left
if col - 1 >= 0:
if input_grid[row][col-1] == 0 and flow_grid[row][col-1] == -1:
percolation_recursive_explore(input_grid, flow_grid,
row, col-1, trace, short)
# Look up
if row - 1 >= 0:
if input_grid[row-1][col] == 0 and flow_grid[row-1][col] == -1:
percolation_recursive_explore(input_grid, flow_grid,
row-1, col, trace, short)