import
java.util.*;
public
class
UpperTangentFinder {
static
class
Point {
int
x, y;
Point() {
x =
0
;
y =
0
;
}
Point(
int
x,
int
y) {
this
.x = x;
this
.y = y;
}
}
static
Point mid =
new
Point();
static
int
quad(Point p) {
if
(p.x >=
0
&& p.y >=
0
)
return
1
;
if
(p.x <=
0
&& p.y >=
0
)
return
2
;
if
(p.x <=
0
&& p.y <=
0
)
return
3
;
return
4
;
}
static
int
orientation(Point a, Point b, Point c) {
int
res = (b.y - a.y) * (c.x - b.x) - (c.y - b.y) * (b.x - a.x);
if
(res ==
0
)
return
0
;
if
(res >
0
)
return
1
;
return
-
1
;
}
static
class
PointComparator
implements
Comparator<Point> {
public
int
compare(Point p1, Point p2) {
Point p =
new
Point(p1.x - mid.x, p1.y - mid.y);
Point q =
new
Point(p2.x - mid.x, p2.y - mid.y);
int
one = quad(p);
int
two = quad(q);
if
(one != two)
return
one - two;
return
p.y * q.x - q.y * p.x;
}
}
static
void
findUpperTangent(List<Point> a, List<Point> b) {
int
n1 = a.size(), n2 = b.size();
int
maxa = Integer.MIN_VALUE;
for
(
int
i =
0
; i < n1; i++) {
maxa = Math.max(maxa, a.get(i).x);
mid.x += a.get(i).x;
mid.y += a.get(i).y;
a.get(i).x *= n1;
a.get(i).y *= n1;
}
a.sort(
new
PointComparator());
for
(
int
i =
0
; i < n1; i++) {
a.get(i).x /= n1;
a.get(i).y /= n1;
}
mid.x =
0
;
mid.y =
0
;
int
minb = Integer.MAX_VALUE;
for
(
int
i =
0
; i < n2; i++) {
mid.x += b.get(i).x;
mid.y += b.get(i).y;
minb = Math.min(minb, b.get(i).x);
b.get(i).x *= n2;
b.get(i).y *= n2;
}
b.sort(
new
PointComparator());
for
(
int
i =
0
; i < n2; i++) {
b.get(i).x /= n2;
b.get(i).y /= n2;
}
if
(minb < maxa) {
List<Point> temp = a;
a = b;
b = temp;
n1 = a.size();
n2 = b.size();
}
int
ia =
0
, ib =
0
;
for
(
int
i =
1
; i < n1; i++) {
if
(a.get(i).x > a.get(ia).x)
ia = i;
}
for
(
int
i =
1
; i < n2; i++) {
if
(b.get(i).x < b.get(ib).x)
ib = i;
}
int
inda = ia, indb = ib;
boolean
done =
false
;
while
(!done) {
done =
true
;
while
(orientation(b.get(indb), a.get(inda), a.get((inda +
1
) % n1)) >
0
)
inda = (inda +
1
) % n1;
while
(orientation(a.get(inda), b.get(indb), b.get((n2 + indb -
1
) % n2)) <
0
) {
indb = (n2 + indb -
1
) % n2;
done =
false
;
}
}
System.out.println(
"upper tangent ("
+ a.get(inda).x +
","
+ a.get(inda).y +
") ("
+ b.get(indb).x +
","
+ b.get(indb).y +
")"
);
}
public
static
void
main(String[] args) {
List<Point> a =
new
ArrayList<>();
a.add(
new
Point(
2
,
2
));
a.add(
new
Point(
3
,
1
));
a.add(
new
Point(
3
,
3
));
a.add(
new
Point(
5
,
2
));
a.add(
new
Point(
4
,
0
));
List<Point> b =
new
ArrayList<>();
b.add(
new
Point(
0
,
1
));
b.add(
new
Point(
1
,
0
));
b.add(
new
Point(
0
, -
2
));
b.add(
new
Point(-
1
,
0
));
findUpperTangent(a, b);
}
}