算法分析学习笔记(一) - 动态连通性问题的并查集算法(下)

三. 实际应用——解决物理化学中的渗滤模型问题

     该问题来自于http://coursera.cs.princeton.edu/algs4/assignments/percolation.html,问题的原版描述如下:
      Percolation. Given a composite systems comprised of randomly distributed insulating and metallic materials: what fraction of the materials need to be metallic so that the composite system is an electrical conductor? Given a porous landscape with water on the surface (or oil below), under what conditions will the water be able to drain through to the bottom (or the oil to gush through to the surface)? Scientists have defined an abstract process known as  percolation to model such situations.
     简单解释下,这就是科学家常说的“渗滤模型”,它通常用来建模如下情况:1)给定一个由绝缘体和导体构成的复合材料,问导体所占比例为多少时该复合材料能够导电?2)给定一块表面上有水或油的多孔地形,在什么情况下水或者油能渗漏到底层去?
     我们用一个N*N的网格来建模这一系统,其中每一个网格要么是开放的(open),要么是阻塞的(blocked),我们在开放网格的基础上定义“满”(full)网格——它是一种特殊的开放网格,可通过上,下,左,右四个方向的一系列临近网格连接到顶层第一行的开放网格上去。若底层行存在满网格,我们就说该系统是“可渗滤的”,也就是说顶层和底层之间存在开放路径,电或者是水可以从顶层渗漏到底层去。图3-1左边是可渗滤系统,而右边则不是。

图3-1 渗滤模型

图3-2 添加虚拟节点的技巧

3.1 要解决的问题     

     假设每一个网格都是独立的,它成为开放网格的概率是p,科学家关心的问题是:整个系统是可渗滤的概率有多大?若p为0,每个网格都是阻塞的,那么整个系统就是不可渗滤的;若p为1,那么整个系统就是可渗滤的。当N足够大,一定存在一个阀值p*,当p大于p*时系统可渗滤,当p小于p*时系统不可渗滤,我们的任务就是找出p*的值。
     我们用有序对(i,j)对网格进行编号,按题目要求,(i,j)的取值在1和N之间,其中(1,1)是最左上角的网格。但具体的实现上我们不打算用二维数组,而是采取将二维数组映射为一维数组的方式,这么做的理由是因为我们要使用并查集算法,而并查集算法是基于一维数组实现的。API的Java语言描述如下所示:
public class Percolation {
   public Percolation(int N)              // create N-by-N grid, with all sites blocked
   public void open(int i, int j)         // open site (row i, column j) if it is not already
   public boolean isOpen(int i, int j)    // is site (row i, column j) open?
   public boolean isFull(int i, int j)    // is site (row i, column j) full?
   public boolean percolates()            // does the system percolate?
}

3.2 具体实现参考     

     实现上,我们用一个一维数组op[]来存储映射过的网格(i,j),op的大小为N * N + 2。我们在原来的N个顶层节点和底层节点的基础上再添加两个虚拟节点,其中op[0]为虚拟顶层节点,op[N * N + 1]为虚拟底层节点,并将各顶层节点与虚拟顶层节点建立连接,各底层节点与虚拟底层节点建立连接,这样只需一次调用就可以检查该模型是否是可渗滤的,如图3-2所示。
 
private final int size;
private boolean[] op; // mark whether it is open or blocked
private final int vtop;
private final int vbot;
private WeightedQuickUnionUF wquf;
private WeightedQuickUnionUF backwash;
public Percolation(int N) {
        if (N < 1) {
                throw new IllegalArgumentException("N must be >= 1");
        }
        size = N;
        wquf = new WeightedQuickUnionUF(size * size + 2);
        backwash = new WeightedQuickUnionUF(size * size + 1);
        // op[vtop] is virtual top and op[vbot] is virtual bottom
        op = new boolean[size * size + 2</
  • 1
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值