Sedgewick& amp;韦恩,练习1.2.3

时间:2013-07-14 12:51:37

标签: java algorithm graphics geometry

塞奇威克的算法&韦恩,练习1.2.3:

  

编写一个带有命令行参数N的{​​{3}}客户端,   minmax并生成N随机2D区间,其宽度为   高度均匀分布在单位中的minmax之间   广场。在StdDraw上绘制它们并打印成对的数量   相交的间隔和间隔的数量   彼此包含在内。

Interval2D公开以下API:

Interval2D(Interval1D x, Interval1D y)
boolean intersects(Interval2D)
boolean contains(Point2D)
double area()
void draw()

是否可以仅使用这些方法检查另一个Interval2D是否包含在其中?

4 个答案:

答案 0 :(得分:1)

A)了解情况:

以1D间隔定义2D间隔A和B:

 A = Ixa x Iya = [x1a, x2a] x [y1a, y2a]
 B = Ixb x Iyb = [x1b, x2b] x [y1b, y2b]

然后

 A is contained in B, iff 
 Ixa = [x1a, x2a] is contained in Ixb [x1b, x2b] and
 Iya = [y1a, y2a] is contained in Iyb = [y1b, y2b].

使用

 I1 = [a, b] is contained in I2 = [c, d] iff c <= a and b <= d.

这类似于Interval2D(http://algs4.cs.princeton.edu/12oop/Interval2D.java.html)和Intervall1D(http://algs4.cs.princeton.edu/12oop/Interval1D.java.html)中交叉方法的实现,只是它们测试条件的逻辑逆。

B)现在你的方法:

如果检查左下角(x1a,y1a)和右上角(x2a,y2a)点,则包含(Point2D)应允许进行测试:

 A is contained in B, iff B contains (x1a, y1a) and B contains (x2a, y2a).

丑陋的是,虽然Interval1D有getters访问私有左右坐标,但Interval2D没有访问它的私有x和y(一维)间隔。 你可以从它的toString()输出解析它们,但这是丑陋和太多的工作。 创建一些超类

public class Rect {
  public Interval1D x;
  public Interval1D y;
  public Interval2D r;
  Rect(Interval1D px, Interval1D py) {
    x = px;
    y = py;
    r = new Interval2D(px, py);
  }
  public boolean contains(Rect that) {
    if (!this.r.contains(new Point2D(that.x.left(), that.y.left()))) return false;
    if (!this.r.contains(new Point2D(that.x.right(), that.y.right()))) return false;
    return true;
  }
}

使用它只是丑陋。

答案 1 :(得分:1)

您可以在Interval1D中使用left()和right()方法,在创建2D间隔期间预先保存它们。

我这样做了

    int intersect = 0;
    int contain = 0;    
    for (int i = 0; i < N; i++) {
        for (int j = i + 1; j < N; j++) {
            if (arr2D[i].intersects(arr2D[j])){
                intersect++;
            }
            if ( (arrX[i].left() <= arrX[j].left() && arrX[i].right() >= arrX[j].right())
                && (arrY[i].left() <= arrY[j].left() && arrY[i].right() >= arrY[j].right())) {
                contain++;
            }   
        }
    }

答案 2 :(得分:0)

使用间隔的上限和下限检查交叉点更有意义。从理论上讲,应该可以只使用列出的方法,但这样做有效可能会很棘手。如果Interval A包含Interval b,那么B中的每个点也都在A中。因此我们可以迭代每个点(如果坐标系基于int而不是double)并检查这个条件。 如果我们面对双打,那么可以使用修改后的技术来生成一个包含方法,该方法将以高概率正确运行。

//Iterate over some subset of points.
if(b.contains(pointP) && !a.contains(pointP))
   return false;

诀窍是找到合适的子集。但我认为保证总是正确的算法要困难得多。考虑一维情况。如果间隔A = (0.5,Math.PI/6)B = [0.4,Math.PI/6]。显然B包含A,但这些方法都不能帮助我们看到它们都具有相同的正确终点,但B 包括那个点,而A则没有。 这些方法如何帮助我们区分这个例子:

A = (0.5,Math.PI/6]B = [0.4,Math.PI/6) 现在只需要选择一点来表明B不包含A:Math.PI/6 这让我觉得这样的算法几乎是不可能的。

答案 3 :(得分:0)

我的解决方案在这里:

package exercise.chapter2.section2;

import edu.princeton.cs.algs4.Interval1D;
import edu.princeton.cs.algs4.Interval2D;
import edu.princeton.cs.algs4.StdOut;
import edu.princeton.cs.algs4.StdRandom;

public class Ex1_2_03 {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        int N = Integer.parseInt(args[0]);
        double min = Double.parseDouble(args[1]);
        double max = Double.parseDouble(args[2]);
        MyInterval2D[] boxes = new MyInterval2D[N];
        for (int i = 0; i < N; i++) {
            double width = StdRandom.uniform(min, max);
            double height = StdRandom.uniform(min, max);

            double xlo = StdRandom.uniform(width, 1.0 - width);
            double xhi = xlo + width;
            double ylo = StdRandom.uniform(height, 1.0 - height);
            double yhi = ylo + height;

            boxes[i] = new MyInterval2D(new Interval1D(xlo, xhi), new Interval1D(ylo, yhi));
            boxes[i].draw();            
        }

        int cintersects = 0;
        int ccontained = 0;
        for (int i = 0; i < N; i++) {
            for (int j = i + 1; j < N; j++) {
                if (boxes[i].intersects(boxes[j])) {
                    cintersects++;
                }
            }
        }

        for (int i = 0; i < N; i++) {
            boxes[i].draw();
            for (int j = 0; j < N; j++) {
                if (i != j && boxes[j].contains(boxes[i])) {
                    ccontained++;
                    break;
                }
            }
        }
        StdOut.println(cintersects);
        StdOut.println(ccontained);
    }

}

class MyInterval2D extends Interval2D {
    private Interval1D xint;
    private Interval1D yint;

    public MyInterval2D(Interval1D xint, Interval1D yint) {
        super(xint, yint);
        this.xint = xint;
        this.yint = yint;
    }

    public boolean contains(MyInterval2D box) {
        if (xint.contains(box.xint.min()) && xint.contains(box.xint.max()) && yint.contains(box.yint.min()) && yint.contains(box.yint.max())) {
            return true;
        }
        return false;
    }

}