Percolation
目标
通过蒙特卡洛模拟来计算 percolation threshold即渗滤阈值。
渗滤
percolation渗滤是一个由绝缘体和金属随机分布的复杂系统。那么它的金属分布在什么情况下会导致它是一个导体。科学家定义了一个抽象的被称作percolation的过程来为这些情况建模。
模型
这个模型被定义为一个n*n的方格来表示。方格site有两种状态:阻塞block和打开open。当一个方格被称为full时,表示这个方格是打开的并且通过一系列与之相邻(上下左右)的打开的方格与最上层的open的方格连接。当一个系统是percolates时,表示该系统最上层的打开的方格与最底层的打开的方格连接。
主要思路
运用WeightedQuickUnionUF数据结构将二维的sites表示为一维
open函数里需要检查上下左右的site是否需要与其union
sites是否percolate可以通过添加一个顶部虚拟site和一个底部虚拟site,最终验证这两个site是否connected。避免了遍历第一行和最后一行的每个site。
backwash
关于backwash问题,这个并不影响percolation的结果,但是作业评判系统会检查full这个函数。
解决方法是创建多一个WeightedQuickUnionUF对象,这个对象只包含顶部虚拟点,在full函数里利用这个对象可以避免backwash。
代码
Percolation
import edu.princeton.cs.algs4.WeightedQuickUnionUF;
public class Percolation {
private WeightedQuickUnionUF sites; // including upper and lower virtual sites
private WeightedQuickUnionUF secSites; // including only upper virtual sites
private int num; // the number of a low of sites
private int opens; // the number of open sites
private boolean[] flags; // flag of the state of site
public Percolation(int n) {
// create n-by-n grid, with all sites blocked
if (n > 0) {
sites = new WeightedQuickUnionUF(n*n+2);
secSites = new WeightedQuickUnionUF(n*n+1);
num = n;
opens = 0;
flags = new boolean[n*n]; // false means blocked
}
else throw new IllegalArgumentException();
}
public void open(int row, int col) {
// open site (row, col) if it is not open already
int ind = xyTo1D(row, col);
if (row > 0 && row <= num && col > 0 && col <= num) {
if (!isOpen(row, col)) {
if (ind <= num) {
sites.union(0, ind);
secSites.union(0, ind);
}
if (ind < (num*num