Programming Assignment 1: Percolation

问题描述可以详见:http://coursera.cs.princeton.edu/algs4/assignments/percolation.html

关于QuickFindUF的javadoc:http://algs4.cs.princeton.edu/15uf/QuickFindUF.java.html

关于WeightedQuickUnionUF的javadoc:http://algs4.cs.princeton.edu/15uf/WeightedQuickUnionUF.java.html

附言:(引用于http://blog.csdn.net/revilwang/article/details/10823467

关于这个模型,其实存在一个问题,在算法课程的论坛上,讨论的热度很高。问题是这样的:

由于引入虚拟的顶层区域和虚拟的底层区域,那么当模型渗透的时候,可能会出现下图的情况

Programming Assignment 1: Percolation

如右边图所示,由于所有的底层区域都和虚拟底层区域相连,所以一旦当区域渗透,则和其他的底层开启区域相连的区域也显示为区域满状态。而实际的情况应该是按照左图所示。这个问题称为 backwash,个人把这个翻译成“回流”。引入虚拟底层区域,很难避免这个问题。讨论的结果,有两种方式可以改进:

1. 不使用虚拟底层区域,只保留顶层,判断是否渗透的时候用虚拟顶层和一个for循环来判断。

2. 保留虚拟底层区域,另外加一个不使用虚拟底层的模型,将两个模型结合在一起来判断是否渗透,通过浪费一些内存来保证效率。

backwash的情况导致Percolation.java在测试时public void isfull(int i, int j) 方法出现错误,这一点从上面两张图也可以明显的看出来。(而解决的办法通过上面两种方法实现)

下面两段代码是从http://www.cnblogs.com/tiny656/p/3820653.html 复制来的,因为自己写的没有考虑到backwash的情况,所以有一些错误,就不挂上来误人子弟了。

Percolation.java

public class Percolation {

    

    private boolean[] matrix;

    private int row, col;

    private WeightedQuickUnionUF wquUF;

    private WeightedQuickUnionUF wquUFTop;

    private boolean alreadyPercolates;

    

    public Percolation(int N) {

        if (N < 1) throw new IllegalArgumentException("Illeagal Argument");

        wquUF = new WeightedQuickUnionUF(N*N+2);

        wquUFTop = new WeightedQuickUnionUF(N*N+1);

        alreadyPercolates = false;

        row = N;

        col = N;

        matrix = new boolean[N*N+1];

    }

    

    private void validate(int i, int j) {

        if (i < 1 || i > row) 

            throw new IndexOutOfBoundsException("row index i out of bounds");

        if (j < 1 || j > col) 

            throw new IndexOutOfBoundsException("col index j out of bounds");        

    }

    

    public void open(int i, int j) {

        validate(i, j);

        int curIdx = (i-1)*col + j; 

        matrix[curIdx] = true;

        if (i == 1) {

            wquUF.union(curIdx, 0);

            wquUFTop.union(curIdx, 0);

        }

        if (i == row) {

            wquUF.union(curIdx, row*col+1);

        }

        

        int[] dx = {1, -1, 0, 0};

        int[] dy = {0, 0, 1, -1};

        for (int dir = 0; dir < 4; dir++) {

            int posX = i + dx[dir];

            int posY = j + dy[dir];

            if (posX <= row && posX >= 1 

                    && posY <= row && posY >= 1 

                    && isOpen(posX, posY)) {

                wquUF.union(curIdx, (posX-1)*col+posY);

                wquUFTop.union(curIdx, (posX-1)*col+posY);

            }

        }

    }

    

    public boolean isOpen(int i, int j) {

        validate(i, j);

        return matrix[(i-1)*col + j];

    }

    

    public boolean isFull(int i, int j) {

        validate(i, j);

        int curIdx = (i-1)*col+j;

        if (wquUFTop.find(curIdx) == wquUFTop.find(0)) return true;

        return false;

    }

    

    public boolean percolates() {

        if (alreadyPercolates) return true;

        if (wquUF.find(0) == wquUF.find(row*col+1)) {

            alreadyPercolates = true;

            return true;

        } 

        return false;

    }

    

    public static void main(String[] args) {

        Percolation perc = new Percolation(2);

        perc.open(1, 1);

        perc.open(1, 2);

        perc.open(2, 1);

        System.out.println(perc.percolates());

    }

    

}

 

PercolationStats.java

public class PercolationStats {

    private double[] x;

    private int expTime;

   public PercolationStats(int N, int T) {    // perform T independent experiments on an N-by-N grid

   

       if (N <= 0 || T <= 0)

           throw new IllegalArgumentException("Illeagal Argument");

       x = new double[T+1];

       expTime = T;

       for (int i = 1; i <= T; i++) {

           Percolation perc = new Percolation(N);

           while (true) {           

               int posX, posY;

               do {

                   posX = StdRandom.uniform(N) + 1;

                   posY = StdRandom.uniform(N) + 1;

               } while(perc.isOpen(posX, posY));

               perc.open(posX, posY);

               x[i] += 1;

                  if (perc.percolates())

                          break;    

           }

           x[i] = x[i]/(double) (N * N);

       }

   }

   public double mean() {                     // sample mean of percolation threshold

   

       double u = 0.0;

       for (int i = 1; i <= expTime; i++) {

       

           u += x[i];

       }

       return u / (double)expTime;

   }

   public double stddev() {                   // sample standard deviation of percolation threshold

   

       double q = 0.0;

       double u = mean();

       for (int i = 1; i <= expTime; i++) {

       

           q += (x[i]-u)*(x[i]-u);

       }

       return Math.sqrt(q / (double)(expTime - 1));

   }

   public double confidenceLo() {            // low  endpoint of 95% confidence interval

   

       double mu = mean();

       double sigma = stddev();

       return mu - 1.96*sigma / Math.sqrt(expTime);

   }

   public double confidenceHi() {           // high endpoint of 95% confidence interval

   

       double mu = mean();

       double sigma = stddev();

       return mu + 1.96*sigma / Math.sqrt(expTime);    

   }



   public static void main(String[] args) {   // test client (described below)

   

       int N = Integer.parseInt(args[0]);

       int T = Integer.parseInt(args[1]);

       PercolationStats percStats = new PercolationStats(N, T);

       StdOut.printf("mean = %f\n", percStats.mean());

       StdOut.printf("stddev = %f\n", percStats.stddev());

       StdOut.printf("95%% confidence interval = %f, %f\n", 

                      percStats.confidenceLo(), percStats.confidenceHi());



   }

}

你可能感兴趣的:(programming)