AOJ1226 Fishnet
問題リンク Fishnet
- 概要
1辺が1の正方形の各辺にN個の釘を打ち、水平方向と鉛直方向に糸を張る。
糸を張るときは必ず(a1, b1),(a2, b2)...(an, bn), (c1, d1),...,(cn, dn)の組の釘に対して張る。
水平方向に張った糸同士、鉛直方向に張った糸同士は交差しない。
糸を張った時に網目ができる。この網目の中で最も面積が大きいものの面積を求めよ。
N<=30
- 解法
水平方向の直線と鉛直方向の直線がN+2本づつ作れる。それをh[N+2], v[N+2]に順番にしまう。
水平方向のとなりあった直線h[i] h[i+1]と鉛直方向の隣り合った直線v[j] v[j+1]に対して交点を4つ求める。
この交点が1つの網目の4頂点に対応するので、外積を使って面積を求めれば網目の面積となる。
これを全ての網目に対して行う。
- ソース
import java.util.Scanner; //Fishnet public class AOJ1226 { double EPS = 1.0e-8; double norm(Point p) { return Math.hypot(p.x, p.y); } double inp(Point p1, Point p2) { return p1.x*p2.x + p1.y*p2.y; } double extp(Point p1, Point p2) { return p1.x*p2.y - p2.x*p1.y; } Point sub(Point p1, Point p2) { return new Point(p1.x-p2.x, p1.y-p2.y); } 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 } Point crosspoint(Line l, Line m) { if(isParallel(l, m)){ throw new IllegalArgumentException("parallel"); } double A = extp(sub(l.t, l.s), sub(m.t, m.s)); double B = extp(sub(l.t, l.s), sub(l.t, m.s)); if (Math.abs(A) < EPS && Math.abs(B) < EPS) return m.s; // same line if (Math.abs(A) < EPS) assert(false); // !!!PRECONDITION NOT SATISFIED!!! Point tp = sub(m.t, m.s); return new Point(m.s.x + B/A*tp.x, m.s.y + B/A*tp.y); } boolean isParallel(Line l, Line m){ Point a = new Point(l.t.x - l.s.x, l.t.y - l.s.y); Point b = new Point(m.t.x - m.s.x, m.t.y - m.s.y); if(Math.abs(Math.abs((a.x*b.x + a.y*b.y)/(Math.hypot(a.x, a.y)*Math.hypot(b.x, b.y)) - 1)) < EPS){ return true; } return false; } class Point { public double x; public double y; public Point(double x_, double y_) { x = x_; y=y_; } } class Line { public Point s,t; public Line(Point s_, Point t_) { s = s_; t = t_; } } void run(){ Scanner sc = new Scanner(System.in); for(;;){ int n = sc.nextInt(); if(n==0)break; Point[][] p = new Point[4][n]; for(int i=0;i<n;i++)p[0][i] = new Point(sc.nextDouble(), 0); for(int i=0;i<n;i++)p[1][i] = new Point(sc.nextDouble(), 1); for(int i=0;i<n;i++)p[2][i] = new Point(0, sc.nextDouble()); for(int i=0;i<n;i++)p[3][i] = new Point(1, sc.nextDouble()); Line[] v = new Line[n+2]; Line[] h = new Line[n+2]; v[0] = new Line(new Point(0, 0), new Point(0, 1)); for(int i=1;i<=n;i++)v[i] = new Line(p[0][i-1], p[1][i-1]); v[n+1] = new Line(new Point(1,0), new Point(1,1)); h[0] = new Line(new Point(0, 0), new Point(1,0)); for(int i=1;i<=n;i++)h[i] = new Line(p[2][i-1], p[3][i-1]); h[n+1] = new Line(new Point(0,1), new Point(1,1)); double max = 0; for(int i=0;i<=n;i++)for(int j=0;j<=n;j++){ Point p1 = crosspoint(h[i], v[j]); Point p2 = crosspoint(h[i+1], v[j]); Point p3 = crosspoint(h[i+1], v[j+1]); Point p4 = crosspoint(h[i], v[j+1]); max = Math.max(max, Math.abs(extp(p1, p2)+extp(p2, p3)+extp(p3, p4)+extp(p4, p1))); } System.out.printf("%.7f\n", max/2); } } public static void main(String[] args) { new AOJ1226().run(); } }