普林斯頓大學演算法公開課第一週作業
阿新 • • 發佈:2018-12-16
今天開始學習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());
}
}