Coursera Algorithms Programming Assignment 1: Percolation(100分)
题目来源http://coursera.cs.princeton.edu/algs4/assignments/percolation.html
我的分析
本次作业根据教授在视频课上提示,可以在grid的上方和下方各加入一个虚节点,grid第一行的open节点都与top虚节点连通,grid最后一行的open节点都与bottom虚节点连通。这样只需判断top虚节点与bottom虚节点是否连通就知道grid是否渗透,而不需要去一一选取特定节点比对了。照着这个思路,我实现了下述模型代码。值得注意的是,模型代码的main中测试方法不是仅仅进行各本地测试就可以了,提交作业的时候会进行自动脚本测试,所以提交的版本main方法中必须读取args[0]中的文件名,并加载文件内容进行生成grid和open对应的site。
import edu.princeton.cs.algs4.In;
import edu.princeton.cs.algs4.StdOut;
import edu.princeton.cs.algs4.WeightedQuickUnionUF;
/**
* @author evasean www.cnblogs.com/evasean/
*/
public class Percolation {
private static final boolean BLOCK = false; // block state
private static final boolean OPEN = true; // open state /* topUF bottomUF n 均为final是因为它们只在构造函数时初始化,后续其值未发生变化 */
private final WeightedQuickUnionUF topUF; // 用来记录与top虚节点的连通性
private final WeightedQuickUnionUF bottomUF;// 用来记录与bottom虚节点的连通性
private final int n; private boolean[][] grid;
private boolean percolateFlag = false; // grid是否渗透的标志
private int openedNum = 0;// 已经open的site数目 public Percolation(int n) {
// create n-by-n grid, with all sites blocked
if (n < 1)
throw new IllegalArgumentException("grid size should be bigger than one !");
this.n = n;
topUF = new WeightedQuickUnionUF(n * n + 1); // 多了一个节点的空间,位置n*n处用来代表虚节点
bottomUF = new WeightedQuickUnionUF(n * n + 1); // 多了一个节点的空间,位置n*n处用来代表虚节点
grid = new boolean[n][n];
// 初始化grid设为block
for (int i = 0; i < n; i++)
for (int j = 0; j < n; j++)
grid[i][j] = BLOCK;
} private void validate(int row, int col) {
if (row < 1 || col < 1 || row > n || col > n)
throw new IllegalArgumentException("input row or col is not illegal!");
} public void open(int row, int col) {
// open site (row, col) if it is not open already
validate(row, col);
if (grid[row - 1][col - 1] == OPEN)
return; grid[row - 1][col - 1] = OPEN;
openedNum++; // n为1时,open一个节点就达到渗透要求
if (n == 1) {
topUF.union(0, 1);
bottomUF.union(0, 1);
percolateFlag = true;
return;
} // 第一行的所有节点都与top虚节点连通
if (row == 1)
topUF.union(n * n, col - 1); // 最后一行的所有节点都与bottom虚节点连通
if (row == n)
bottomUF.union(n * n, (n - 1) * n + col - 1); // 与上方节点的连通性
if (row > 1 && grid[row - 2][col - 1] == OPEN) {
topUF.union((row - 2) * n + col - 1, (row - 1) * n + col - 1);
bottomUF.union((row - 2) * n + col - 1, (row - 1) * n + col - 1);
} // 与下方节点的连通性
if (row < n && grid[row][col - 1] == OPEN) {
topUF.union(row * n + col - 1, (row - 1) * n + col - 1);
bottomUF.union(row * n + col - 1, (row - 1) * n + col - 1);
} // 与左侧节点的连通性
if (col > 1 && grid[row - 1][col - 2] == OPEN) {
topUF.union((row - 1) * n + col - 2, (row - 1) * n + col - 1);
bottomUF.union((row - 1) * n + col - 2, (row - 1) * n + col - 1);
} // 与右侧节点的连通性
if (col < n && grid[row - 1][col] == OPEN) {
topUF.union((row - 1) * n + col, (row - 1) * n + col - 1);
bottomUF.union((row - 1) * n + col, (row - 1) * n + col - 1);
} /*
* 判断条件!percolateFlag是为了防止渗透以后的重复判断 判断条件openedNum>=n
* 是因为openedNum达到n时才有可能渗透,在未达到n之前,不需要进行后续判断
* 一个节点open的时候刚好使grid渗透的条件是该节点同时与top虚节点和bottom虚节点连通
*/
if (!percolateFlag && openedNum >= n && topUF.connected(n * n, (row - 1) * n + col - 1)
&& bottomUF.connected(n * n, (row - 1) * n + col - 1))
percolateFlag = true; } public boolean isOpen(int row, int col) {
// is site (row, col) open?
validate(row, col);
return grid[row - 1][col - 1] == OPEN;
} /**
* 一个节点只有同时在open状态并且与top虚节点连通时才是full状态
* @param row
* @param col
* @return
*/
public boolean isFull(int row, int col) {
// is site (row, col) full?
validate(row, col);
if (isOpen(row, col) && topUF.connected(n * n, (row - 1) * n + col - 1))
return true;
else
return false;
} public int numberOfOpenSites() {
// number of open sites
return openedNum;
} public boolean percolates() {
// does the system percolate?
return percolateFlag;
} //打印一些便于查看的信息
private void printCheckResult(int row, int col) {
StdOut.println("p(" + row + "," + col + ") is open=" + isOpen(row, col) + ";is full=" + isFull(row, col)
+ ";percolates=" + percolates());
} /**
* 作业提交时main需要调用该方法,因为提交后在线脚本要用一堆input文件进行测试
*
* @param arg0
*/
private static void fileInputCheck(String arg0) {
// test client (optional)
In in = new In(arg0);//读入input文件名,并加载文件内容
String s = null;
int n = -1;
//读入grid的n
while (in.hasNextLine()) {
s = in.readLine();
if (s != null && !s.trim().equals(""))
break;
}
s = s.trim();
n = Integer.parseInt(s);
Percolation p = new Percolation(n); //读入open的site坐标
while (in.hasNextLine()) {
s = in.readLine();
if (s != null && !s.trim().equals("")) {
s = s.trim();//去掉输入字符串头尾空格
String[] sa = s.split("\\s+");//去掉中间所有空格
if (sa.length != 2)
break;
int row = Integer.parseInt(sa[0]);
int col = Integer.parseInt(sa[1]);
p.open(row, col);
}
} } /**
* 本地测试专用
*/
private static void generateCheck() {
// test client (optional)
Percolation p = new Percolation(3);
int row = 1, col = 3;
p.open(row, col);
p.printCheckResult(row, col);
row = 2;
col = 3;
p.open(row, col);
p.printCheckResult(row, col);
row = 3;
col = 3;
p.open(row, col);
p.printCheckResult(row, col);
row = 3;
col = 1;
p.open(row, col);
p.printCheckResult(row, col);
row = 2;
col = 1;
p.open(row, col);
p.printCheckResult(row, col);
row = 1;
col = 1;
p.open(row, col);
p.printCheckResult(row, col);
} public static void main(String[] args) {
//generateCheck();
fileInputCheck(args[0]);
}
}
仿真分析这一部分比较简单,其中需要注意的地方就是“随机选取row和col进行open”,如果简单的用random(int n),选取[0,n)获取row和col,会有很多重复节点被选中,随着n越大,命中率就越低。于是我采用生成一个[0,n*n)的数组,数组内容随机排序,依次读取数组内容,就相当于随机取site。
import edu.princeton.cs.algs4.StdOut;
import edu.princeton.cs.algs4.StdRandom;
import edu.princeton.cs.algs4.StdStats;
/**
* @author evasean www.cnblogs.com/evasean/
*/
public class PercolationStats {
/* t fractions 均为final是因为它们只在构造函数时初始化,后续其值未发生变化*/
private final int t;//尝试次数
private final double[] fractions;//每一次尝试的渗透率得分 private double mean;
private double stddev; public PercolationStats(int n, int trials) {
// perform trials independent experiments on an n-by-n grid
if (n <= 0 || trials <= 0)
throw new IllegalArgumentException("n ≤ 0 or trials ≤ 0");
t = trials;
fractions = new double[t];
for (int i = 0; i < t; i++) {//t次尝试
Percolation p = new Percolation(n);
int openNum = 0;
//为了实现随机open一个site,模仿QuickUnion的定位方法
//先生成一个[0,n*n)的数组,数组内容随机排序,依次读取数组内容,就相当于随机取site
int[] rand = StdRandom.permutation(n * n);
for (int pos : rand) {
//pos = (row-1)*n + col -1
int row = pos / n + 1;
int col = pos % n + 1;
p.open(row, col);
openNum++;
//只有openNum>=n时才有判断是否渗透的必要
if (openNum >= n && p.percolates())
break;
}
double pt = (double) openNum / (n * n);//单次尝试的渗透率
fractions[i] = pt;
}
/* 作业提交时的某个测试案例要求mean()、stddev()、confidenceLo()、confidenceHi()
* 在任何时候任何次序调用的情况下都必须返回相同的值,故需要在构造函数中计算mean和stddev
*/
//作业提交时的某个测试案例要调用一次StdStats.mean方法
mean = StdStats.mean(fractions);
//作业提交时的某个测试案例要求要调用一次StdStats.stddev方法
stddev = StdStats.stddev(fractions);
} public double mean() {
// sample mean of percolation threshold
return mean;
} public double stddev() {
// sample standard deviation of percolation threshold
return stddev;
} public double confidenceLo() {
// low endpoint of 95% confidence interval
return mean - 1.96 * stddev / Math.sqrt(t);
} public double confidenceHi() {
// high endpoint of 95% confidence interval
return mean + 1.96 * stddev / Math.sqrt(t);
} public static void main(String[] args) {
// test client (described below)
int n = Integer.parseInt(args[0]);
int t = Integer.parseInt(args[1]);
PercolationStats ps = new PercolationStats(n, t);
StdOut.printf("%-25s %s %f \n", "means", "=", ps.mean());
StdOut.printf("%-25s %s %f \n", "stddev", "=", ps.stddev());
StdOut.printf("%-25s %s%f%s%f%s\n", "95% confidence interval", "= [", ps.confidenceLo(), ", ",
ps.confidenceHi(), "]");
}
}
Coursera Algorithms Programming Assignment 1: Percolation(100分)的更多相关文章
- Coursera Algorithms Programming Assignment 3: Pattern Recognition (100分)
题目原文详见http://coursera.cs.princeton.edu/algs4/assignments/collinear.html 程序的主要目的是寻找n个points中的line seg ...
- Coursera Algorithms Programming Assignment 2: Deque and Randomized Queue (100分)
作业原文:http://coursera.cs.princeton.edu/algs4/assignments/queues.html 这次作业与第一周作业相比,稍微简单一些.有三个编程练习:双端队列 ...
- Coursera Algorithms Programming Assignment 4: 8 Puzzle (100分)
题目原文:http://coursera.cs.princeton.edu/algs4/assignments/8puzzle.html 题目要求:设计一个程序解决8 puzzle问题以及该问题的推广 ...
- Coursera Algorithms Programming Assignment 5: Kd-Trees (98分)
题目地址:http://coursera.cs.princeton.edu/algs4/assignments/kdtree.html 分析: Brute-force implementation. ...
- Algorithms : Programming Assignment 3: Pattern Recognition
Programming Assignment 3: Pattern Recognition 1.题目重述 原题目:Programming Assignment 3: Pattern Recogniti ...
- Programming Assignment 1: Percolation
问题描述可以详见:http://coursera.cs.princeton.edu/algs4/assignments/percolation.html 关于QuickFindUF的javadoc:h ...
- AlgorithmsI Programming Assignment 1: Percolation
3种版本的答案,第一种使用virtual top and bottom site, 但有backwash的问题,解决这个问题有两种方法: 1. 使用2个WQUUF, 但会增加memory. One f ...
- Algorithms: Design and Analysis, Part 1 - Programming Assignment #1
自我总结: 1.编程的思维不够,虽然分析有哪些需要的函数,但是不能比较好的汇总整合 2.写代码能力,容易挫败感,经常有bug,很烦心,耐心不够好 题目: In this programming ass ...
- Coursera课程 Programming Languages, Part A 总结
Coursera CSE341: Programming Languages 感谢华盛顿大学 Dan Grossman 老师 以及 Coursera . 碎言碎语 这只是 Programming La ...
随机推荐
- css学习笔记---盒模型,布局
1.外边距叠加 当一个元素出现在另一个元素上面时第一个元素的底边距与第二个元素的上边距发生叠加,元素被包含时也有可能会发生叠加(如果没有内边距和边框),如果一个空元素没有内边距和边框本身也会发生上下边 ...
- OpenCV:使用OpenCV3随机森林进行统计特征多类分析
原文链接:在opencv3中的机器学习算法练习:对OCR进行分类 本文贴出的代码为自己的训练集所用,作为参考.可运行demo程序请拜访原作者. CNN作为图像识别和检测器,在分析物体结构分布的多类识别 ...
- 【sqli-labs】 less56 GET -Challenge -Union -14 queries allowed -Variation3 (GET型 挑战 联合查询 只允许14次查询 变化3)
单引号括号闭合 http://192.168.136.128/sqli-labs-master/Less-56/?id=1')%23 http://192.168.136.128/sqli-labs- ...
- codeforces_738D
D. Sea Battle time limit per test 1 second memory limit per test 256 megabytes input standard input ...
- C# 把时间 月 //把第一个0替换为空
string str = "2019-01"; //name: "2019-01月" str = str.Substring(str.Length - , ); ...
- linux下如何限制普通用户更改密码
问题描述: 为了方便linux管理员对所有用户的进行管理,如何限制普通用户更改密码? 解决方法: 禁止普通用户更改密码: /usr/bin/passwd 若要允许普通用户更改密码: /usr/bin/ ...
- 10.mysql事务管理及python操作
在用户操作MySQL过程中,对于一般简单的业务逻辑或中小型程序而言,无需考虑应用MySQL事务.但在比较复杂的情况下,往往用户在执行某些数据操作过程中,需要通过一组SQL语句执行多项并行业务逻辑或程序 ...
- hdu 5178 pairs
pairs 问题描述 John 在X轴上拥有nn个点,他们的坐标分别为$(x[i],0),(i=0,1,2,…,n-1)$. 他想知道有多少对< a,b ><a,b>满足|x[ ...
- PAT 1039. Course List for Student
Zhejiang University has 40000 students and provides 2500 courses. Now given the student name lists o ...
- AtCoder ABC 085C/D
C - Otoshidama 传送门:https://abc085.contest.atcoder.jp/tasks/abc085_c 有面值为10000.5000.1000(YEN)的纸币.试用N张 ...