• 中文
    • English
  • 注册
  • 查看作者
  • 《算法第四版》课后练习题1.1.31答案

    习题1.1.31 

    随机连接。编写一段程序,从命令行接受一个整数 N 和 double 值 p(0 到 1 之间)作为参数, 在一个圆上画出大小为 0.05 且间距相等的 N 个点,然后将每对点按照概率 p 用灰线连接。

    要点分析

    因为本题设计到很多图库的操作,所以我们可以先找出所有的操作可能用到的方法,再根据题意一步步的解题即可:

    一.
    因为本题设计到画圆操作,所以要用到本书为我们提供的标准绘图库StdDraw(详见课本P26),画圆需要用到的方法为:

    public static void circle(double x, double y, double r) //x和y为圆心坐标,r为半径

    二.
    在圆上画出的大小0.05的点,设置点的大小为0.05需要的方法为(详见课本P26):

    static void setPenRadius(double r) //将画笔的粗细半径设为r

    三.
    在圆上画出的大小0.05的点,画点需要用到的方法为(详见课本P26):

    static void point(double x, double y) //将画笔的颜色设置为c

    四.
    每对点需要用灰色连接,点设置为灰色需要的方法为(详见课本P26):

    static void setPenColor(Color c) //根据参数坐标画出一个以(x,y)为中心的点

    五.
    获取概率p需要的方法为(详见课本18页)

    static boolean bernoulli(double p)//返回真的概率为p

    六.
    每对点之间的连线,需要用到的方法为(详见课本P26)

    static void line(double x0, double y0, double x1, double y1)
    //根据参数的坐标画出一条连接点(x0,y0)和点(x1,y1)的线段

    七.
    通过第3步我们知道,所有点的操作都需要点的坐标,所以我们可以创建一个坐标类,用于存储坐标值,为了方便操作,我们可以使用匿名内部类的方式创建Point类(这一步也可以直接用一个二维数组代替):

    static class Point {
        double x;
        double y;
    
        public Point(double x, double y) {
            super();
            this.x = x;
            this.y = y;
        }
    }

    八.
    知道需要使用的方法后,我们再来分析本题,本题的一大难点就是获取N个点的坐标,如果将圆的周长看成一个直线,将N个点,等举例的在这条线上画出来很简单,但是一旦变成圆,便没有了思路,在查询了kyson博客后,才知道可以使用角度的方法来解决这个问题,可以设N个点的点与点之间的角度为360/N:

    for (int i = 0; i < N; i++) {
        points[i] = new Point(0.5 + 0.5 * Math.cos(angle * i * Math.PI / 180),
                0.5 + 0.5 * Math.sin(angle * i * Math.PI / 180));
        StdDraw.point(points[i].x, points[i].y);
    }

    九.
    因为本文用到了静态类,这里补充一些静态类基础的知识点:

    静态内部类特点

    • 可以当做类的静态成员
    • 使用static修饰的内部类叫做静态内部类
    • 静态内部类可以当做和外部类平级的类
    • 静态内部类的实例化
    • 外部类名.内部类名 实例名 =new 外部类名.内部类名(参数)

    静态内部类的限制

    • 内部类不能和外部类重名
    • 静态内部类不能访问外部类的非静态属性和方法
    • 外部类不能访问静态内部类的非静态属性和方法

    参考答案

    package tv.zhangjia.one.one;
    
    import edu.princeton.cs.algs4.StdDraw;
    import edu.princeton.cs.algs4.StdRandom;
    
    import java.awt.*;
    
    
    public class Test {
        static class Point {
            double x;
            double y;
    
            public Point(double x, double y) {
                super();
                this.x = x;
                this.y = y;
            }
        }
        public static void main(String[] args) {
            int N = Integer.parseInt(args[0]);
            double p = Double.parseDouble(args[1]);
            Point[] points = new Point[N];
            double angle = 360.0 / N;
            StdDraw.circle(0.5, 0.5, 0.5);
            StdDraw.setPenRadius(0.05);
            for (int i = 0; i < N; i++) {
                points[i] = new Point(0.5 + 0.5 * Math.cos(angle * i * Math.PI / 180),
                        0.5 + 0.5 * Math.sin(angle * i * Math.PI / 180));
                StdDraw.point(points[i].x, points[i].y);
            }
            StdDraw.setPenColor(Color.GRAY);
            for (int i = 0; i < N - 1; i++) {
                for (int j = i + 1; j < N; j++) {
                    if (StdRandom.bernoulli(p)) {
                        StdDraw.line(points[i].x, points[i].y, points[j].x, points[j].y);
                    }
                }
            }
            //该for循环将每个点两两按照StdRandom.bernoulli(p)的结果选择是否连接
            //如果StdRandom.bernoulli(p)为true,则分别将这两个点的坐标作为StdDraw.line()的参数画出一条连接线段
        }
    }

     

     

     

  • 0
  • 1
  • 0
  • 4.9k
  • 梁兴健

    请登录之后再进行评论

    登录
  • 0
    博主,还更新吗?
  • 单栏布局 侧栏位置: