普林斯顿算法课第三周作业

来源:互联网 发布:pos机软件 编辑:程序博客网 时间:2024/06/05 01:58

第三周作业模式识别

Programming Assignment 3: Pattern Recognition


题目地址:http://coursera.cs.princeton.edu/algs4/assignments/collinear.html

------------------------------------------

这一周的问题是在一个给出N个随即点的平面上,
画出所有所在路径超过四个点的直线。
首先还是老老实实的从第一个类开始说起。
public class Point implements Comparable<Point> {   public final Comparator<Point> SLOPE_ORDER;        // compare points by slope to this point   public Point(int x, int y)                         // construct the point (x, y)   public   void draw()                               // draw this point   public   void drawTo(Point that)                   // draw the line segment from this point to that point   public String toString()                           // string representation   public    int compareTo(Point that)                // is this point lexicographically smaller than that point?   public double slopeTo(Point that)                  // the slope between this point and that point}




第一个类的主要功能是创建点的分布,并通过StdDraw类输出,其中运用到了比较器。
很良心的,其中前四个方法已经给出。
我们只需要把后两个和比较器写出。
1. public    int compareTo(Point that)                // is this point lexicographically smaller than that point?
也就是是否这个点是否比那个点小,比较标准给出了,
y0<y1或y0=y1但x0<x1时 表示this.point<that.point


2.public double slopeTo(Point that)                  // the slope between this point and that point


计算两点间斜率,官方说明上给的很清楚,包括各类情况的返回值,就不多说了。
3.public final Comparator<Point> SLOPE_ORDER; 
用来比较斜率的比较器,第一次用不是很会用。后来摸透了以后感觉很方便。
代码如下:
import java.util.Comparator;public class Point implements Comparable<Point> {    // compare points by slope    public final Comparator<Point> SLOPE_ORDER= new SlopeOrder();;       // YOUR DEFINITION HERE    private final int x;                              // x coordinate    private final int y;                              // y coordinate        private class SlopeOrder implements Comparator<Point>{                public int compare(Point p1, Point p2) {              double slopeP1 = slopeTo(p1);              double slopeP2 = slopeTo(p2);              if (slopeP1 == slopeP2) return 0;              if (slopeP1 < slopeP2) return -1;              else return +1;          }                }      // create the point (x, y)    public Point(int x, int y) {        /* DO NOT MODIFY */        this.x = x;        this.y = y;    }    // plot this point to standard drawing    public void draw() {        /* DO NOT MODIFY */        StdDraw.point(x, y);    }    // draw line between this point and that point to standard drawing    public void drawTo(Point that) {        /* DO NOT MODIFY */        StdDraw.line(this.x, this.y, that.x, that.y);    }    // slope between this point and that point    public double slopeTo(Point that) {        /* YOUR CODE HERE */    if (this.compareTo(that) == 0)              return Double.NEGATIVE_INFINITY;          else if (this.x == that.x)              return Double.POSITIVE_INFINITY;          else if (this.y == that.y)              return +0;          else              return (that.y - this.y) * 1.0 / (that.x - this.x);      }    // is this point lexicographically smaller than that one?    // comparing y-coordinates and breaking ties by x-coordinates    public int compareTo(Point that) {        /* YOUR CODE HERE */    if (this.y < that.y || (this.y == that.y && this.x < that.x))              return -1;          else if (this.y == that.y && this.x == that.x)              return 0;          else              return 1;          }    // return string representation of this point    public String toString() {        /* DO NOT MODIFY */        return "(" + x + ", " + y + ")";    }    // unit test    public static void main(String[] args) {        // rescale coordinates and turn on animation mode        StdDraw.setXscale(0, 32768);        StdDraw.setYscale(0, 32768);        StdDraw.show(0);        StdDraw.setPenRadius(0.01);  // make the points a bit larger        // read in the input        String filename = args[0];        In in = new In(filename);        int N = in.readInt();        for (int i = 0; i < N; i++) {            int x = in.readInt();            int y = in.readInt();            Point p = new Point(x, y);            p.draw();                }        // display to screen all at once        StdDraw.show(0);        // reset the pen radius        StdDraw.setPenRadius();        }}







第二个类是用暴力方法连线


暴力解法的思想很简单,用枚举法对所有点进行排序后判断斜率,三个斜率相等后则画出直线。
当然时间很慢,复杂度是N^4


代码如下:
public class Brute {public static void main(String[] args) {        // rescale coordinates and turn on animation mode        StdDraw.setXscale(0, 32768);        StdDraw.setYscale(0, 32768);                     // read in the input        String filename = args[0];        In in = new In(filename);        int N = in.readInt();        Point[] pointArray=new Point[N];        for (int i = 0; i < N; i++) {            int x = in.readInt();            int y = in.readInt();            Point p = new Point(x, y);            pointArray[i] = p;            p.draw();        }        Quick3way.sort(pointArray);        BruteForce(pointArray);          StdDraw.show(0);  }private static void BruteForce(Point[] pointArray){          int N = pointArray.length;          for (int i=0; i<N; i++){              for (int j=i+1; j<N; j++){                  for (int k=j+1; k<N; k++){                      for (int l=k+1; l<N; l++){                          if (pointArray[i].slopeTo(pointArray[j]) == pointArray[i].slopeTo(pointArray[k]) &&                              pointArray[i].slopeTo(pointArray[j]) == pointArray[i].slopeTo(pointArray[l])){                              StdOut.println(pointArray[i] + " -> " + pointArray[j] + " -> "  + pointArray[k] + " -> "  + pointArray[l]);                              pointArray[i].drawTo(pointArray[l]);                          }                      }                  }              }          }      }  }





第三个类是用一个很快的、基于排序的解决方法。
在给定点P上,对所有斜率进行排序,如果存在三个点或以上的斜率相等,则共线。
当然还是要枚举P点,不过排序的话复杂度会下降很多。
同时要避免同一条线段多次输出,需要用到compareTo。


代码如下:

import java.util.Arrays;public class Fast {public static void main(String[] args){// rescale coordinates and turn on animation mode        StdDraw.setXscale(0, 32768);        StdDraw.setYscale(0, 32768);        String filename = args[0];        In in = new In(filename);        int N = in.readInt();        if (N < 4){        return;        }        Point[] pointArray = new Point[N];        for (int i = 0; i < N; i++) {            int x = in.readInt();            int y = in.readInt();            Point p = new Point(x, y);            pointArray[i] = p;            p.draw();        }        Quick3way.sort(pointArray);        FastMethod(pointArray);        StdDraw.show(0);    }private static void FastMethod(Point[] pointArray){int N = pointArray.length;for (int i=0; i<N; i++){Point origPoint = pointArray[i];Point[] otherPoint = new Point[N-1];for (int j=0; j<pointArray.length; j++){if (j < i) otherPoint[j] = pointArray[j];if (j > i) otherPoint[j-1] = pointArray[j];}Arrays.sort(otherPoint, origPoint.SLOPE_ORDER);int count = 0;int index = 0;double tempSlope = origPoint.slopeTo(otherPoint[0]);for (int j=0; j<otherPoint.length;j++){if (Double.compare(origPoint.slopeTo(otherPoint[j]),  tempSlope) == 0){count++;continue;}else{if (count >=3){if (otherPoint[index].compareTo(origPoint) >=0){StdOut.print(origPoint + " -> ");for (int k=index; k<j-1; k++){StdOut.print(otherPoint[k] + " -> ");}StdOut.println(otherPoint[j-1]);origPoint.drawTo(otherPoint[j-1]);}}count = 1;index = j;tempSlope = origPoint.slopeTo(otherPoint[j]);}}if (count >= 3){if (otherPoint[index].compareTo(origPoint) >= 0){StdOut.print(origPoint + " -> ");for (int k=index; k<otherPoint.length - 1; k++){StdOut.print(otherPoint[k] + " -> ");}StdOut.println(otherPoint[otherPoint.length-1]);origPoint.drawTo(otherPoint[otherPoint.length-1]);}}}StdDraw.show(0);}}


0 0
原创粉丝点击