今天开始学习coursera上的算法公开课,感觉第一周作业难度还不低23333
作业要求:http://coursera.cs.princeton.edu/algs4/assignments/percolation.html
主要内容是利用加权QuickUnion方法计算蒙特卡洛模型的阈值。中间经历了几次修改,根据warning把类中某些用于初始化的变量添加了final属性
将一些计算(比如均值和标准差)放在了构造函数里并储存,减少方法的调用,增加计算速度,解决了Timing问题。
Test13 14 15有关isFull通不过是因为表中最后一层会通过底部虚拟节点连接起来,这就导致最后一层的isFull方法有问题,网上的方法都是新建一个不包括底部节点的WeightedQuickUnionUF,我觉得不是很好,之后想一下解决办法。最终成绩95
Percolation.java
import edu.princeton.cs.algs4.WeightedQuickUnionUF;
public class Percolation {
private boolean[][] table;
private final WeightedQuickUnionUF wq;
private final int nval;
private int op;
public Percolation(int n) {
if (n <= 0) throw new IllegalArgumentException(); //当n小于等于0时抛出异常
nval = n;
wq = new WeightedQuickUnionUF(n * n + 2); //定义一个加权QuickUnion,在最上层和最下层分别添加一个虚拟节点
table = new boolean[n][n];
for (int i = 0; i <= n - 1; i++) {
for (int j = 0; j < n - 1; j++) {
table[i][j] = false; //初始化nxn的表格
}
}
op = 0; //将状态为open的格子的计数值置零
}
private int map2Dto1D(int row, int col) {
return row * nval + col; //将行列坐标展开为一维序列值
}
public void open(int row, int col) {
if (row < 1 || row > nval || col < 1 || col > nval) throw new IllegalArgumentException();
int trow = row - 1; //实际的索引从0开始
int tcol = col - 1;
int in = map2Dto1D(trow, tcol); //将要open的格子位置先保存下来,之后要多次使用
if (table[trow][tcol] == false) {
op++; //状态为open的格子数加一
table[trow][tcol] = true; //true为open状态
if (row == 1) {
wq.union(tcol, nval * nval); //第一行要跟最上面的虚拟节点连接
}
if (row == nval) { //最后一行要跟最下面的虚拟节点连接
wq.union(map2Dto1D(trow, tcol), nval * nval + 1);
}
if (row > 1 && table[trow - 1][tcol] == true) { //与周围的节点连接
wq.union(map2Dto1D(trow - 1, tcol), in);
}
if (col > 1 && table[trow][tcol - 1] == true) {
wq.union(map2Dto1D(trow, tcol - 1), in);
}
if (col < nval && table[trow][tcol + 1] == true) {
wq.union(map2Dto1D(trow, tcol + 1), in);
}
if (row < nval && table[trow + 1][tcol] == true) {
wq.union(map2Dto1D(trow + 1, tcol), in);
}
}
}
public boolean isOpen(int row, int col) {
if (row < 1 || row > nval || col < 1 || col > nval) throw new IllegalArgumentException();
return table[row - 1][col - 1];
}
public boolean isFull(int row, int col) {
if (row < 1 || row > nval || col < 1 || col > nval) throw new IllegalArgumentException();
return wq.connected(map2Dto1D(row - 1, col - 1), nval * nval);
}
public int numberOfOpenSites() {
return op;
}
public boolean percolates() { //判断是否渗透
return wq.connected(nval * nval, nval * nval + 1);
}
}
PercolationStats.java
import edu.princeton.cs.algs4.StdIn;
import edu.princeton.cs.algs4.StdRandom;
import edu.princeton.cs.algs4.StdStats;
public class PercolationStats {
private final double threshold[];
private final int trials;
private final double shu = 1.96;
private double meanVal;
private double stddevVal;
public PercolationStats(int n, int trials) {
if (n <= 0 || trials <= 0) throw new IllegalArgumentException();
this.trials = trials;
threshold = new double[trials];
for (int i = 1; i <= trials; i++) { //试验次数循环
Percolation per = new Percolation(n);
while (per.percolates() == false) { //循环直到渗透
int r = StdRandom.uniform(n) + 1; //生成随机坐标
int c = StdRandom.uniform(n) + 1;
per.open(r, c); //open选定的格子
}
threshold[i - 1] = (double) per.numberOfOpenSites() / (n * n); //循环完毕后保存阈值
}
meanVal = StdStats.mean(threshold);
stddevVal = StdStats.stddev(threshold);
}
public double mean() { //计算各次试验阈值的均值
return meanVal;
}
public double stddev() { //计算标准差
return stddevVal;
}
public double confidenceLo() {
return meanVal - shu * stddevVal / Math.sqrt(trials);
}
public double confidenceHi() {
return meanVal + shu * stddevVal / Math.sqrt(trials);
}
public static void main(String[] args) { //主程序
int n = StdIn.readInt(); //输入一个n和试验次数T
int T = StdIn.readInt();
PercolationStats m = new PercolationStats(n, T);
System.out.println(m.mean());
System.out.println(m.stddev());
System.out.println(m.confidenceLo());
System.out.println(m.confidenceHi());
}
}