Percolation
实现Percolation模型。
用蒙特卡罗模拟估计渗滤阈值的值。
关于backwash问题:有了一个虚拟底层位置,如果网格已经渗透了。这时判断其中一个位置(与底部相连,并且底部是打开的,与虚拟底层位置相连)是否满(即与虚拟顶层位置是相连的),那么不管这个位置是不是真的满,结果总会是满的。因为网格已经渗透了,那么虚拟顶层位置与虚拟底层位置总是相连的,而这个位置与虚拟顶层位置是相连的,这时候再判断它是不是满(与虚拟顶层位置相连),结果当然总是为真。
这里提供了两种方法解决backwash,即回流问题
Percolation with top virtual site
即带有虚拟位置的网格。
同时需要建立两个WeightedQuickUnionUF 对象,一个同时有虚拟顶层位置和虚拟底层位置,这样判断是否渗透很容易。另一个只有虚拟顶层位置,这就避免了回流问题,用来判断是否满。
由于建立了两个WeightedQuickUnionUF 对象,所以 内存使用没有完全过关,得到了97分。
Percolation.java
import edu.princeton.cs.algs4.StdIn;
import edu.princeton.cs.algs4.StdOut;
import edu.princeton.cs.algs4.WeightedQuickUnionUF;
/**
* The {@code Percolation} class provides methods for calculating the Percolation.
* <p>
* Creates two WeightedQuickUnionUF objects to solve the backwash problem.
*
* @author zhangyu
* @date 2017.2.27
*/
public class Percolation
{
private int size; // size of created grid
private int[] status; // record the status of each site
private WeightedQuickUnionUF grid;
private WeightedQuickUnionUF gridNoVBottom;
/**
* Initializes two WeightedQuickUnionUF object. One has two
* virtual sites, and the other one has only one top site.
* Set state of each site blocked.
*
* @param n size of created grid
* @throws IllegalArgumentException if n < 1
*/
public Percolation(int n)
{
if (n < 1) throw new IllegalArgumentException("Grid size out of range");
size = n;
status = new int[n * n];
for (int i = 0; i < n * n; i++) status[i] = 0;
grid = new WeightedQuickUnionUF(n*n + 2);
gridNoVBottom = new WeightedQuickUnionUF(n*n + 1);
}
/**
* open site (row, col) if it is not open already.
*
* @param row abscissa of the grid
* @param col ordinate of the grid
*/
public void open(int row, int col)
{
int idx = xyTo1D(row, col);
validate(row, col);
status[idx] = 1;
if (1 == row) // connect to the virtual site
{
grid.union(idx, size * size);
gridNoVBottom.union(idx, size * size);
}
if (size == row) grid.union(idx, size*size + 1);
int[] xDiff = {-1, 1, 0, 0};
int[] yDiff = {
0, 0, -1, 1};
for (int i = 0; i < 4; i++)
{
int adjX = row + xDiff[i];
int adjY = col + yDiff[i];
if (adjX > 0 && adjX <= size)
{
if (adjY > 0 && adjY <= size)
{
int adjPosIdx = xyTo1D(adjX, adjY);
if (1 == status[adjPosIdx])
{
grid.union(idx, adjPosIdx);
gridNoVBottom.union(idx, adjPosIdx);
}
}
}
}
}
/**
* Determine whether the site (row, col) is open.
*
* @param row abscissa of the grid
* @param col ordinate of the grid
* @return true if the site (row, col) is open;
* false otherwise
*/
public boolean isOpen(