递归探测算法的实现

迷茫童鞋的阅读指南

 

该项目的详细描述和算法的具体说明

请参见前一篇 Project2 Percolation in Grids 网格渗透

本人给出了percolation_provided.py的函数说明

目前已完成水波探测算法的实现

 

该算法的关键是实现explore函数中递归,及percolation_recursiveexplore的初始调用

 

 

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)

 

 

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

 

Step4:

  设计这个explore函数,还是比较头疼的。关键是要考虑到如何在这里面实现递归,我们从项目中的描述来分解这个问题:

 

假设一个单元与[i][j]相邻,流能够到达(i也可以为第一行),input_grid[i][j]=0flow_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


 

  具体实现如下:
Look Code
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)

 

 

Step5:

  回到前面的函数,如果short被定义为False。那么无论最后是否发生渗透,explore函数表面上看是void类型的,其实会返回一个值None。那么就需要在函数体加上一段渗透判断。判断依据就是flow_grid的最后一行是否有元素的值为*

 

    for col in range(size):
        
if flow_grid[size-1][col] == '*':
            
return flow_grid, True

 

 

最后这里是完整的代码:

 

I’m Code
 1 #! /usr/bin/env python
 2 from visual import rate
 3 from percolation_provided import *
 4 
 5 def percolation_recursive(input_grid, trace=True, short=False):
 6     """
 7     Determine whether or not a grid percolates, and which cells are filled.
 8     Like before, short is True if you want the algorithm to stop immediately
 9     when it percolates, rather than exploring the entire grid.
10     """
11     size = len(input_grid)
12     flow_grid = grid(size, -1)
13 
14     #start exploration from each space in top (zeroth) row
15     for col in range(size):
16         if explore(input_grid, flow_grid, 0, col, trace, short):
17             return flow_grid, True
18 
19     #check last (size-1'th) row for full spaces
20     for col in range(size):
21         if flow_grid[size-1][col] == '*':
22             return flow_grid, True
23 
24     #no full spaces in bottom row; doesn't percolate
25     return flow_grid, False
26 
27 def explore(input_grid, flow_grid, row, col, trace, short):
28     """Explore the grid, marking unblocked cells as full as they are explored"""
29     size = len(input_grid)
30     if input_grid[row][col] == 0:
31         flow_grid[row][col] = '*'
32         
33         if trace:
34             visualize(flow_grid, input_grid)
35             rate(2)
36 
37         #explore neighboring cells
38 
39         if short:
40             if row + 1 == size:
41                 return True
42 
43         # Look down
44         if row + 1 < size:
45             if input_grid[row+1][col] == 0 and flow_grid[row+1][col] == -1:
46                 percolation_recursive_explore(input_grid, flow_grid,
47                                               row+1, col, trace, short)
48         # Look right
49         if col + 1 < size:
50             if input_grid[row][col+1== 0 and flow_grid[row][col+1== -1:
51                 percolation_recursive_explore(input_grid, flow_grid,
52                                               row, col+1, trace, short)
53 
54         # Look left
55         if col - 1 >= 0:
56             if input_grid[row][col-1== 0 and flow_grid[row][col-1== -1:
57                 percolation_recursive_explore(input_grid, flow_grid,
58                                               row, col-1, trace, short)
59 
60         # Look up
61         if row - 1 >= 0:
62             if input_grid[row-1][col] == 0 and flow_grid[row-1][col] == -1:
63                 percolation_recursive_explore(input_grid, flow_grid,
64                                               row-1, col, trace, short)

 

 

  

 

 

posted @ 2011-08-09 22:13  牛皮糖NewPtone  阅读(530)  评论(0编辑  收藏  举报