「數據結構」普林斯頓算法課第一週作業

「數據結構」普林斯頓算法課第一週作業 Algorithm I, Princeton

編程作業: Percolation

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.

The model. We model a percolation system using an n-by-n grid of sites. Each site is either open or blocked. A full site is an open site that can be connected to an open site in the top row via a chain of neighboring (left, right, up, down) open sites. We say the system percolates if there is a full site in the bottom row. In other words, a system percolates if we fill all open sites connected to the top row and that process fills some open site on the bottom row. (For the insulating/metallic materials example, the open sites correspond to metallic materials, so that a system that percolates has a metallic path from top to bottom, with full sites conducting. For the porous substance example, the open sites correspond to empty space through which water might flow, so that a system that percolates lets water fill open sites, flowing from top to bottom.)

思路

視頻課中已經給出了trick,就是增加虛擬頂端(virtual top site)和底端(virtual bottom site)。
因此,percolates的話只要檢查虛擬頂端和虛擬底端是否聯通即可。
增加虛擬頂端有很多方法,可以將網格變成n*(n+2)個,也可以將網格變成n*n+2個,方法有很多。下面代碼展示的是n*n+2的方法,虛擬頂端直接佔用數組中index=0的項,方便了一點。
site的三種狀態:blockedempty openfull open
另外還要注意並查集算法中的union方法不等價於open

第一部分代碼展示

/* *****************************************************************************
 *  Name: Albert
 *  Date: 16 Aug.
 *  Description:
 **************************************************************************** */

import edu.princeton.cs.algs4.StdIn;
import edu.princeton.cs.algs4.WeightedQuickUnionUF;

public class Percolation {

    private WeightedQuickUnionUF perc;
    private boolean[] flag;
    private int sqrt;
    private int number;
    private int numberOfOpenSites;


    // creates n-by-n grid, with all sites initially blocked
    public Percolation(int n) {
        if (n <= 0)
            throw new IllegalArgumentException("n must > 0!");
        sqrt = n;
        number = n * n + 2;
        perc = new WeightedQuickUnionUF(number);
        flag = new boolean[number];
        for (int i = 1; i < number - 1; i++) flag[i] = false;
        flag[0] = true;
        flag[number - 1] = true;
        // union the virtual top site and first n sites
        for (int i = 1; i <= n; i++)
            perc.union(0, i);
        // union the virtual bottom site and last n sites
        for (int i = n * n; i > n * n - n; i--)
            perc.union(n * n + 1, i);
    }

    // index = (row - 1) * sqrt + col

    // opens the site (row, col) if it is not open already
    public void open(int row, int col) {
        if (row <= 0)
            throw new IllegalArgumentException("row must > 0!");
        if (col <= 0)
            throw new IllegalArgumentException("row must > 0!");
        if (flag[(row - 1) * sqrt + col] == false) {
            // open sites
            // up site
            if (row != 1 && flag[(row - 1) * sqrt + col - sqrt])
                perc.union((row - 1) * sqrt + col,
                           (row - 1) * sqrt + col - sqrt);
            // down site
            if (row != sqrt && flag[(row - 1) * sqrt + col + sqrt])
                perc.union((row - 1) * sqrt + col,
                           (row - 1) * sqrt + col + sqrt);
            // left site
            if (flag[(row - 1) * sqrt + col - 1] == true && col != 1)
                perc.union((row - 1) * sqrt + col,
                           (row - 1) * sqrt + col - 1);
            // right site
            if (flag[(row - 1) * sqrt + col + 1] == true && col != sqrt)
                perc.union((row - 1) * sqrt + col,
                           (row - 1) * sqrt + col + 1);
            // change flag
            flag[(row - 1) * sqrt + col] = true;
            // add numberofopensites
            numberOfOpenSites++;
        }
    }

    // is the site (row, col) open?
    public boolean isOpen(int row, int col) {
        if (row <= 0)
            throw new IllegalArgumentException("row must > 0!");
        if (col <= 0)
            throw new IllegalArgumentException("row must > 0!");
        return flag[(row - 1) * sqrt + col];
    }

    // is the site (row, col) full?
    public boolean isFull(int row, int col) {
        if (row <= 0)
            throw new IllegalArgumentException("row must > 0!");
        if (col <= 0)
            throw new IllegalArgumentException("row must > 0!");
        if (isOpen(row, col)) {
            // connected(self, 0)
            return perc.connected(0, (row - 1) * sqrt + col);
        }
        else return false;
    }

    // returns the number of open sites
    public int numberOfOpenSites() {
        return numberOfOpenSites;
    }

    // does the system percolate?
    public boolean percolates() {
        return perc.connected(0, sqrt * sqrt + 1);
    }

    // test client (optional)
    public static void main(String[] args) {
        int N = StdIn.readInt();
        Percolation pe = new Percolation(N);
        pe.open(1, 1);
        pe.open(2, 1);
        System.out.println(pe.percolates());
    }
}

第二部分代碼展示

/* *****************************************************************************
 *  Name: Albert
 *  Date: 16 Aug.
 *  Description:
 **************************************************************************** */

import edu.princeton.cs.algs4.StdOut;
import edu.princeton.cs.algs4.StdRandom;
import edu.princeton.cs.algs4.StdStats;

public class PercolationStats {

    private double[] threshold;
    private double[] confidence_interval;
    private int T;

    // perform independent trials on an n-by-n grid
    public PercolationStats(int n, int trials) {
        if (trials <= 0)
            throw new IllegalArgumentException("Trials must > 0!");
        if (n <= 0)
            throw new IllegalArgumentException("n must > 0!");

        T = trials;
        threshold = new double[T];
        int times = 0;

        while (times < T) {
            // each pocolation experimental
            Percolation perc = new Percolation(n);
            int count = 0;
            // generate the x,y(less than n) to open sites
            while (true) {
                count++;
                int x = StdRandom.uniform(n) + 1;
                int y = StdRandom.uniform(n) + 1;

                if (perc.isOpen(x, y)) {
                    continue;
                }
                else
                    perc.open(x, y);

                if (perc.percolates()) break;

            }
            threshold[times] = (double) perc.numberOfOpenSites() / (n * n);

            times++;

        }

    }

    // sample mean of percolation threshold
    public double mean() {
        return StdStats.mean(threshold);
    }

    // sample standard deviation of percolation threshold
    public double stddev() {
        return StdStats.stddev(threshold);
    }

    // low endpoint of 95% confidence interval
    public double confidenceLo() {
        return (mean() - (1.96 * stddev()) / (Math.sqrt(T)));
    }

    // high endpoint of 95% confidence interval
    public double confidenceHi() {
        return (mean() + (1.96 * stddev()) / (Math.sqrt(T)));
    }

    // test client (see below)
    public static void main(String[] args) {
        PercolationStats percolationStats = new PercolationStats(200, -1);
        StdOut.println(percolationStats.mean());
        StdOut.println(percolationStats.stddev());
        StdOut.println(percolationStats.confidenceLo());
        StdOut.println(percolationStats.confidenceHi());
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章