博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Coursera Algorithms Programming Assignment 1: Percolation(100分)
阅读量:5214 次
发布时间:2019-06-14

本文共 11833 字,大约阅读时间需要 39 分钟。

题目来源http://coursera.cs.princeton.edu/algs4/assignments/percolation.html

作业分为两部分:建立模型和仿真实验。
最关键的部分就是建立模型对象。模型对象要求如下:
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.)
 
边界要求:  By convention, the row and column indices are integers between 1 and 
n, where (1, 1) is the upper-left site: Throw a 
java.lang.IllegalArgumentException if any argument to 
open()
isOpen(), or 
isFull() is outside its prescribed range. The constructor should throw a 
java.lang.IllegalArgumentException if 
n ≤ 0.
 
性能要求: 
 The constructor should take time proportional to 
n2; all methods should take constant time plus a constant number of calls to the union–find methods 
union()
find()
connected(), and 
count().

我的分析

本次作业根据教授在视频课上提示,可以在grid的上方和下方各加入一个虚节点,grid第一行的open节点都与top虚节点连通,grid最后一行的open节点都与bottom虚节点连通。这样只需判断top虚节点与bottom虚节点是否连通就知道grid是否渗透,而不需要去一一选取特定节点比对了。照着这个思路,我实现了下述模型代码。值得注意的是,模型代码的main中测试方法不是仅仅进行各本地测试就可以了,提交作业的时候会进行自动脚本测试,所以提交的版本main方法中必须读取args[0]中的文件名,并加载文件内容进行生成grid和open对应的site。

1 import edu.princeton.cs.algs4.In;  2 import edu.princeton.cs.algs4.StdOut;  3 import edu.princeton.cs.algs4.WeightedQuickUnionUF;  4 /**  5  * @author evasean www.cnblogs.com/evasean/  6  */  7 public class Percolation {  8     private static final boolean BLOCK = false; // block state  9     private static final boolean OPEN = true; // open state 10  11     /* topUF bottomUF n 均为final是因为它们只在构造函数时初始化,后续其值未发生变化 */ 12     private final WeightedQuickUnionUF topUF; // 用来记录与top虚节点的连通性 13     private final WeightedQuickUnionUF bottomUF;// 用来记录与bottom虚节点的连通性 14     private final int n; 15  16     private boolean[][] grid; 17     private boolean percolateFlag = false; // grid是否渗透的标志 18     private int openedNum = 0;// 已经open的site数目 19  20     public Percolation(int n) { 21         // create n-by-n grid, with all sites blocked 22         if (n < 1) 23             throw new IllegalArgumentException("grid size should be bigger than one !"); 24         this.n = n; 25         topUF = new WeightedQuickUnionUF(n * n + 1); // 多了一个节点的空间,位置n*n处用来代表虚节点 26         bottomUF = new WeightedQuickUnionUF(n * n + 1); // 多了一个节点的空间,位置n*n处用来代表虚节点 27         grid = new boolean[n][n]; 28         // 初始化grid设为block 29         for (int i = 0; i < n; i++) 30             for (int j = 0; j < n; j++) 31                 grid[i][j] = BLOCK; 32     } 33  34     private void validate(int row, int col) { 35         if (row < 1 || col < 1 || row > n || col > n) 36             throw new IllegalArgumentException("input row or col is not illegal!"); 37     } 38  39     public void open(int row, int col) { 40         // open site (row, col) if it is not open already 41         validate(row, col); 42         if (grid[row - 1][col - 1] == OPEN) 43             return; 44  45         grid[row - 1][col - 1] = OPEN; 46         openedNum++; 47  48         // n为1时,open一个节点就达到渗透要求 49         if (n == 1) { 50             topUF.union(0, 1); 51             bottomUF.union(0, 1); 52             percolateFlag = true; 53             return; 54         } 55  56         // 第一行的所有节点都与top虚节点连通 57         if (row == 1) 58             topUF.union(n * n, col - 1); 59  60         // 最后一行的所有节点都与bottom虚节点连通 61         if (row == n) 62             bottomUF.union(n * n, (n - 1) * n + col - 1); 63  64         // 与上方节点的连通性 65         if (row > 1 && grid[row - 2][col - 1] == OPEN) { 66             topUF.union((row - 2) * n + col - 1, (row - 1) * n + col - 1); 67             bottomUF.union((row - 2) * n + col - 1, (row - 1) * n + col - 1); 68         } 69  70         // 与下方节点的连通性 71         if (row < n && grid[row][col - 1] == OPEN) { 72             topUF.union(row * n + col - 1, (row - 1) * n + col - 1); 73             bottomUF.union(row * n + col - 1, (row - 1) * n + col - 1); 74         } 75  76         // 与左侧节点的连通性 77         if (col > 1 && grid[row - 1][col - 2] == OPEN) { 78             topUF.union((row - 1) * n + col - 2, (row - 1) * n + col - 1); 79             bottomUF.union((row - 1) * n + col - 2, (row - 1) * n + col - 1); 80         } 81  82         // 与右侧节点的连通性 83         if (col < n && grid[row - 1][col] == OPEN) { 84             topUF.union((row - 1) * n + col, (row - 1) * n + col - 1); 85             bottomUF.union((row - 1) * n + col, (row - 1) * n + col - 1); 86         } 87  88         /* 89          * 判断条件!percolateFlag是为了防止渗透以后的重复判断 判断条件openedNum>=n 90          * 是因为openedNum达到n时才有可能渗透,在未达到n之前,不需要进行后续判断 91          * 一个节点open的时候刚好使grid渗透的条件是该节点同时与top虚节点和bottom虚节点连通 92          */ 93         if (!percolateFlag && openedNum >= n && topUF.connected(n * n, (row - 1) * n + col - 1) 94                 && bottomUF.connected(n * n, (row - 1) * n + col - 1)) 95             percolateFlag = true; 96  97     } 98  99     public boolean isOpen(int row, int col) {100         // is site (row, col) open?101         validate(row, col);102         return grid[row - 1][col - 1] == OPEN;103     }104 105     /**106      * 一个节点只有同时在open状态并且与top虚节点连通时才是full状态107      * @param row108      * @param col109      * @return110      */111     public boolean isFull(int row, int col) {112         // is site (row, col) full?113         validate(row, col);114         if (isOpen(row, col) && topUF.connected(n * n, (row - 1) * n + col - 1))115             return true;116         else117             return false;118     }119 120     public int numberOfOpenSites() {121         // number of open sites122         return openedNum;123     }124 125     public boolean percolates() {126         // does the system percolate?127         return percolateFlag;128     }129 130     //打印一些便于查看的信息131     private void printCheckResult(int row, int col) {132         StdOut.println("p(" + row + "," + col + ") is open=" + isOpen(row, col) + ";is full=" + isFull(row, col)133                 + ";percolates=" + percolates());134     }135 136     /**137      * 作业提交时main需要调用该方法,因为提交后在线脚本要用一堆input文件进行测试138      * 139      * @param arg0140      */141     private static void fileInputCheck(String arg0) {142         // test client (optional)143         In in = new In(arg0);//读入input文件名,并加载文件内容144         String s = null;145         int n = -1;146         //读入grid的n147         while (in.hasNextLine()) {148             s = in.readLine();149             if (s != null && !s.trim().equals(""))150                 break;151         }152         s = s.trim();153         n = Integer.parseInt(s);154         Percolation p = new Percolation(n);155         156         //读入open的site坐标157         while (in.hasNextLine()) {158             s = in.readLine();159             if (s != null && !s.trim().equals("")) {160                 s = s.trim();//去掉输入字符串头尾空格161                 String[] sa = s.split("\\s+");//去掉中间所有空格162                 if (sa.length != 2)163                     break;164                 int row = Integer.parseInt(sa[0]);165                 int col = Integer.parseInt(sa[1]);166                 p.open(row, col);167             }168         }169 170     }171 172     /**173      * 本地测试专用174      */175     private static void generateCheck() {176         // test client (optional)177         Percolation p = new Percolation(3);178         int row = 1, col = 3;179         p.open(row, col);180         p.printCheckResult(row, col);181         row = 2;182         col = 3;183         p.open(row, col);184         p.printCheckResult(row, col);185         row = 3;186         col = 3;187         p.open(row, col);188         p.printCheckResult(row, col);189         row = 3;190         col = 1;191         p.open(row, col);192         p.printCheckResult(row, col);193         row = 2;194         col = 1;195         p.open(row, col);196         p.printCheckResult(row, col);197         row = 1;198         col = 1;199         p.open(row, col);200         p.printCheckResult(row, col);201     }202 203     public static void main(String[] args) {204         //generateCheck();205         fileInputCheck(args[0]);206     }207 }

 

仿真分析这一部分比较简单,其中需要注意的地方就是“随机选取row和col进行open”,如果简单的用random(int n),选取[0,n)获取row和col,会有很多重复节点被选中,随着n越大,命中率就越低。于是我采用生成一个[0,n*n)的数组,数组内容随机排序,依次读取数组内容,就相当于随机取site。

1 import edu.princeton.cs.algs4.StdOut; 2 import edu.princeton.cs.algs4.StdRandom; 3 import edu.princeton.cs.algs4.StdStats; 4 /** 5  * @author evasean www.cnblogs.com/evasean/ 6  */ 7 public class PercolationStats { 8     /* t fractions 均为final是因为它们只在构造函数时初始化,后续其值未发生变化*/ 9     private final int t;//尝试次数10     private final double[] fractions;//每一次尝试的渗透率得分11     12     private double mean;13     private double stddev;14 15     public PercolationStats(int n, int trials) {16         // perform trials independent experiments on an n-by-n grid17         if (n <= 0 || trials <= 0)18             throw new IllegalArgumentException("n ≤ 0 or trials ≤ 0");19         t = trials;20         fractions = new double[t];21         for (int i = 0; i < t; i++) {
//t次尝试22 Percolation p = new Percolation(n);23 int openNum = 0;24 //为了实现随机open一个site,模仿QuickUnion的定位方法25 //先生成一个[0,n*n)的数组,数组内容随机排序,依次读取数组内容,就相当于随机取site26 int[] rand = StdRandom.permutation(n * n);27 for (int pos : rand) {28 //pos = (row-1)*n + col -129 int row = pos / n + 1; 30 int col = pos % n + 1;31 p.open(row, col);32 openNum++;33 //只有openNum>=n时才有判断是否渗透的必要34 if (openNum >= n && p.percolates())35 break;36 }37 double pt = (double) openNum / (n * n);//单次尝试的渗透率38 fractions[i] = pt;39 }40 /* 作业提交时的某个测试案例要求mean()、stddev()、confidenceLo()、confidenceHi()41 * 在任何时候任何次序调用的情况下都必须返回相同的值,故需要在构造函数中计算mean和stddev42 */43 //作业提交时的某个测试案例要调用一次StdStats.mean方法44 mean = StdStats.mean(fractions);45 //作业提交时的某个测试案例要求要调用一次StdStats.stddev方法46 stddev = StdStats.stddev(fractions);47 }48 49 public double mean() {50 // sample mean of percolation threshold51 return mean;52 }53 54 public double stddev() {55 // sample standard deviation of percolation threshold56 return stddev;57 }58 59 public double confidenceLo() {60 // low endpoint of 95% confidence interval61 return mean - 1.96 * stddev / Math.sqrt(t);62 }63 64 public double confidenceHi() {65 // high endpoint of 95% confidence interval66 return mean + 1.96 * stddev / Math.sqrt(t);67 }68 69 public static void main(String[] args) {70 // test client (described below)71 int n = Integer.parseInt(args[0]);72 int t = Integer.parseInt(args[1]);73 PercolationStats ps = new PercolationStats(n, t);74 StdOut.printf("%-25s %s %f \n", "means", "=", ps.mean());75 StdOut.printf("%-25s %s %f \n", "stddev", "=", ps.stddev());76 StdOut.printf("%-25s %s%f%s%f%s\n", "95% confidence interval", "= [", ps.confidenceLo(), ", ",77 ps.confidenceHi(), "]");78 }79 }

 

转载于:https://www.cnblogs.com/evasean/p/7204501.html

你可能感兴趣的文章
Java核心技术:Java异常处理
查看>>
Python 学习笔记一
查看>>
引入列表,将对话分类添加到对应列表中
查看>>
回文子串
查看>>
Count Numbers
查看>>
React——JSX
查看>>
编写高质量代码改善C#程序的157个建议——建议110:用类来代替enum
查看>>
最大公约数求解
查看>>
网卡bond技术
查看>>
UITabbarController的UITabbarItem(例:"我的")点击时,判断是否登录
查看>>
机器学习之支持向量机(一):支持向量机的公式推导
查看>>
对【SQL SERVER 分布式事务解决方案】的心得补充
查看>>
UNIX基础知识之输入和输出
查看>>
【洛谷 P1666】 前缀单词 (Trie)
查看>>
python之装饰器
查看>>
对称加密和非对称加密
查看>>
数据库锁机制及乐观锁,悲观锁的并发控制
查看>>
图像处理中双线性插值
查看>>
RobHess的SIFT代码解析之RANSAC
查看>>
bzoj3944:Sum
查看>>