递归探测算法的实现

迷茫童鞋的阅读指南

 

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

请参见前一篇 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]=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


 

  具体实现如下:
ExpandedBlockStart.gif 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

 

 

最后这里是完整的代码:

 

ExpandedBlockStart.gif 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)

 

 

  

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值