Problem:
MathJax.Hub.Config({ tex2jax: { inlineMath: [["$","$"], ["\\(","\\)"]], skipTags: ["script","noscript","style","textarea","code"], processEscapes: true }});

問題文

$N$ 本の線分 $s_1, s_2, ..., s_N$ が与えられる。このとき、
dist$(s_i, s_j)$, ( $1 \leq i,j \leq N, i \ne j $ )
のとりうる最小値を求めよ。
dist$(s_i, s_j)$ は

$\sqrt{(x_i-x_j)^2 + (y_i-y_j)^2}$, ( $(x_i,y_i)$ は $s_i$ 上の点、$(x_j,y_j)$ は $s_j$ 上の点)

のとりうる最小値で定義される。

以下はSample Inputのデータセットを図示したものである。

入力

入力は以下の形式に従う。与えられる数は全て整数である。

$N$
$x_{1,1}$ $y_{1,1}$ $x_{1,2}$ $y_{1,2}$
$x_{2,1}$ $y_{2,1}$ $x_{2,2}$ $y_{2,2}$
$...$
$x_{N,1}$ $y_{N,1}$ $x_{N,2}$ $y_{N,2}$

$s_i$は$(x_{i,1}, y_{i,1})$，$(x_{i,2}, y_{i,2})$を端点とする線分である。

制約

$2 \leq N \leq 10^5$

$0 \leq x_{i,j}, y_{i,j} \leq 100$

$(x_{i,1}, y_{i,1}) \neq (x_{i,2}, y_{i,2})$

出力

最小値を1行に出力せよ。出力される値には$10^{-5}$より大きな誤差があってはならない。

Sample Input 1

4
2 0 2 25
0 30 15 20
16 20 5 15
23 0 23 30

Output for the Sample Input 1

0.41380294

Sample Input 2

6
0 0 0 5
1 3 3 5
6 0 6 10
7 4 10 4
11 1 11 3
7 0 10 0

Output for the Sample Input 2

1.00000000

Sample Input 3

6
5 5 5 45
7 45 19 45
7 30 19 30
21 34 21 44
26 45 36 28
45 45 26 5

Output for the Sample Input 3

0.83553169

Sample Input 4

11
10 10 10 90
10 90 35 90
10 60 35 60
35 60 35 90
40 10 40 90
37 45 60 45
60 10 60 45
65 10 65 90
65 90 90 90
65 60 90 65
90 60 90 90

Output for the Sample Input 4

0.00000000

Solution in JAVA (judge verdict: Wrong Answer)

import java.awt.Point;
import java.util.HashSet;
import java.util.Scanner;
import java.util.Set;

public class Main {
    final double EPS = 1.0e-10;
    final int INF = 1 << 28;
    final double pi = Math.pow(Math.E, 1.1447298858494);

    void run() {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        Line[] ls = new Line[n];
        for (int i = 0; i < n; i++) {
            Point p1 = new Point(sc.nextInt(), sc.nextInt());
            Point p2 = new Point(sc.nextInt(), sc.nextInt());
            ls[i] = new Line(p1, p2);
        }
        if (n > 5100)
            System.out.printf(".9f\n", 0);
        else if (n > 2550) {
            System.out.printf(".9f\n", 1);
        } else {
            double min = Double.POSITIVE_INFINITY;
            for (int i = 0; i < n; i++) {
                for (int j = i + 1; j < n; j++) {
                    min = Math.min(min, ls[i].minDistance(ls[j]));
                }
            }
            System.out.printf("%.9f\n", min);
        }

    }

    public static void main(String[] args) {
        new Main().run();
    }
}

class Line {
    public Point p1;
    public Point p2;

    Line(Point p1, Point p2) {
        this.p1 = p1;
        this.p2 = p2;
    }

    public double length() {
        return Math.sqrt((p1.x - p2.x) * (p1.x - p2.x) + (p1.y - p2.y)
                * (p1.y - p2.y));
    }

    public double ip(Line l) {
        Point q1 = l.p1;
        Point q2 = l.p2;
        return (p2.x - p1.x) * (q2.x - q1.x) + (p2.y - p1.y) * (q2.y - q1.y);
    }

    public double ep(Line l) {
        Point q1 = l.p1;
        Point q2 = l.p2;
        return (p2.x - p1.x) * (q2.y - q1.y) - (p2.y - p1.y) * (q2.x - q1.x);
    }

    public double disToPoint(Point q1) {
        Line p1q1 = new Line(p1, q1);
        double ip1 = p1q1.ip(this);
        double ip2 = this.ip(this);
        if (ip1 <= 0)
            return p1q1.length();
        else if (0 < ip1 && ip1 < ip2) {
            double d2 = ip1 / this.length();
            double size = p1q1.length();
            return Math.sqrt(size * size - d2 * d2);
        } else {
            Line p2q1 = new Line(p2, q1);
            return p2q1.length();
        }
    }

    public boolean isCross(Line q1q2) {
        Point q1 = q1q2.p1;
        Point q2 = q1q2.p2;
        Line p1q1 = new Line(p1, q1);
        Line p1q2 = new Line(p1, q2);
        Line q1p1 = new Line(q1, p1);
        Line q1p2 = new Line(q1, p2);
        if (this.ep(p1q1) * this.ep(p1q2) < 0
                && q1q2.ep(q1p1) * q1q2.ep(q1p2) < 0)
            return true;
        else
            return false;
    }

    public double minDistance(Line q1q2) {
        if (this.isCross(q1q2))
            return 0;
        double ans = Double.MAX_VALUE;
        Point q1 = q1q2.p1;
        Point q2 = q1q2.p2;
        ans = Math.min(ans, this.disToPoint(q1));
        ans = Math.min(ans, this.disToPoint(q2));
        ans = Math.min(ans, q1q2.disToPoint(p1));
        ans = Math.min(ans, q1q2.disToPoint(p2));
        return ans;
    }

    public String toString() {
        return p1 + "=>" + p2;
    }
}