AOJ0153 Triangle and Circle
問題リンク Triangle and Circle
- 解法
線分と点の距離が使いこなせればいける幾何問題です。
まずB(三角形が円内に収まる)を調べます。円の中心と、三角形の頂点との距離が全てR以下ならBです。
次に円の中心が三角形の内部にあるかどうかと、三角形の各辺と円の中心の距離の最小値rを調べます。
中心が三角形内部にあって、R<=rならばAです。
中心が三角形外部にあり、R
- ソース
import java.util.Scanner; //Triangle and Circle public class AOJ0153 { public static class Point { public double x; public double y; public Point(double x_, double y_) { x = x_; y=y_; } } public static class Line { public Point s,t; public Line(Point s_, Point t_) { s = s_; t = t_; } } public static double distanceSP(Line s, Point p) { Point r = proj(s, p); if (intersectSP(s, r)) return norm(sub(r, p)); return Math.min(norm(sub(s.s, p)), norm(sub(s.t, p))); } public static boolean intersectSP(Line s, Point p) { return ccw(s.s, s.t, p) == 0; } public static int ccw(Point a, Point b, Point c) { Point p = sub(b, a); Point q = sub(c, a); if(extp(p, q) > EPS) return 1; // counter clockwise if(extp(p, q) < -EPS)return -1; // clockwise if(inp(p, q) < -EPS) return 2; // c--a--b on line if(Math.abs(norm(p) - norm(q)) < EPS) return -2; // a--b--c on line return 0; // a--c--b(or a--c=b) on line } public static Point sub(Point p1, Point p2) { return new Point(p1.x-p2.x, p1.y-p2.y); } public static Point proj(Line l, Point p) { double t = inp(sub(p, l.s), sub(l.s, l.t)) / Math.pow(norm(sub(l.s, l.t)),2); Point tp = sub(l.s, l.t); return new Point(l.s.x + t*tp.x, l.s.y + t*tp.y); } public static double inp(Point p1, Point p2) { return p1.x*p2.x + p1.y*p2.y; } public static double extp(Point p1, Point p2) { return p1.x*p2.y - p2.x*p1.y; } public static final double EPS = 1.0e-8; public static double norm(Point p) { return Math.hypot(p.x, p.y); } public static void main(String[] args) { Scanner sc = new Scanner(System.in); while(true){ Point pp = new Point(sc.nextDouble(), sc.nextDouble()); if(pp.x==0&&pp.y==0)break; Point[] p = new Point[3]; p[0]=pp; for(int i=1;i<3;i++)p[i]=new Point(sc.nextDouble(),sc.nextDouble()); Point c = new Point(sc.nextDouble(),sc.nextDouble()); double r = sc.nextDouble(); boolean isB = true; for(int i=0;i<3;i++){ if(!(Math.pow(c.x-p[i].x, 2)+Math.pow(c.y-p[i].y, 2)<=r*r))isB = false; } if(isB){ System.out.println("b");continue; } boolean left = true; boolean right = true; double min = Integer.MAX_VALUE; double max = 0; for(int i=0;i<3;i++){ double ex = extp(sub(p[(i+1)%3], p[i]), sub(c, p[i])); if(ex < 0)left = false; else if(ex > 0)right = false; Line l = new Line(p[i], p[(i+1)%3]); //逆向きの線分も考えないと通らない AOJ0129参照 Line m = new Line(p[(i+1)%3], p[i]); double d = Math.max(distanceSP(l, c), distanceSP(m, c)); min = Math.min(min, d); max = Math.max(max, d); } boolean in = left|right; if(in && min >= r)System.out.println("a"); else if(!in && min > r)System.out.println("d"); else System.out.println("c"); } } }