1 import java
.io
.BufferedReader
;
2 import java
.io
.FileReader
;
3 import java
.io
.PrintWriter
;
4 import java
.io
.IOException
;
7 public class asteroids_petr
implements Runnable
{
8 static final int MAX_POWER
= 3;
15 Point(double x
, double y
, double z
) {
33 public void rotateXY(double v
) {
34 double nx
= x
* Math
.cos(v
) - y
* Math
.sin(v
);
35 double ny
= x
* Math
.sin(v
) + y
* Math
.cos(v
);
41 static class Point2D
implements Comparable
<Point2D
> {
46 Point2D(double x
, double y
) {
51 public int compareTo(Point2D point2D
) {
52 return Double
.compare(angle
, point2D
.angle
);
64 public Plane(Point p1
, Point p2
, Point p3
) {
65 a
= (p2
.z
- p1
.z
) * (p3
.y
- p1
.y
) - (p2
.y
- p1
.y
) * (p3
.z
- p1
.z
);
66 b
= (p2
.x
- p1
.x
) * (p3
.z
- p1
.z
) - (p2
.z
- p1
.z
) * (p3
.x
- p1
.x
);
67 c
= (p2
.y
- p1
.y
) * (p3
.x
- p1
.x
) - (p2
.x
- p1
.x
) * (p3
.y
- p1
.y
);
68 double z
= Math
.sqrt(a
* a
+ b
* b
+ c
* c
);
72 d
= -(a
* p1
.x
+ b
* p1
.y
+ c
* p1
.z
);
75 public int side(Point p
) {
76 double z
= sideDouble(p
);
77 if (Math
.abs(z
) < 1e-11)
85 public double sideDouble(Point p
) {
86 return a
* p
.x
+ b
* p
.y
+ c
* p
.z
+ d
;
90 static class Polyhedron
{
94 for (Point p
: points
)
99 for (Point p
: points
)
103 double integrate(double[] what
) {
104 Set
<Double
> allXs
= new TreeSet
<Double
>();
105 for (Point p
: points
)
109 for (Double cur
: allXs
) {
111 double[] areas
= new double[MAX_POWER
+ 1];
112 double[] xs
= new double[MAX_POWER
+ 1];
113 for (int i
= 0 ; i
<= MAX_POWER
; ++i
) {
114 xs
[i
] = (prev
* (MAX_POWER
- i
) + cur
* i
) / MAX_POWER
;
115 areas
[i
] = getArea(xs
[i
]) * evalPolynomial(what
, xs
[i
]);
117 sum
+= (cur
- prev
) / 8.0 * (areas
[0] + 3 * areas
[1] + 3 * areas
[2] + areas
[3]);
124 private double evalPolynomial(double[] koef
, double x
) {
126 for (int i
= koef
.length
- 1; i
>= 0; --i
)
127 res
= res
* x
+ koef
[i
];
131 static Random random
= new Random();
133 private double getArea(double x
) {
134 List
<Point2D
> p2d
= new ArrayList
<Point2D
>();
135 for (Point p1
: points
) {
137 p2d
.add(new Point2D(p1
.y
, p1
.z
));
141 for (Point p2
: points
) {
146 p2d
.add(new Point2D(p1
.y
+ (p2
.y
- p1
.y
) * (x
- p1
.x
) / (p2
.x
- p1
.x
), p1
.z
+ (p2
.z
- p1
.z
) * (x
- p1
.x
) / (p2
.x
- p1
.x
)));
152 Point2D corner
= new Point2D(0, 0);
153 double totalWeight
= 0.0;
154 for (Point2D p
: p2d
) {
155 double weight
= random
.nextDouble();
156 corner
.x
+= weight
* p
.x
;
157 corner
.y
+= weight
* p
.y
;
158 totalWeight
+= weight
;
160 double dx
= -corner
.x
/ totalWeight
;
161 double dy
= -corner
.y
/ totalWeight
;
162 for (Point2D p
: p2d
) {
165 p
.angle
= Math
.atan2(p
.y
, p
.x
);
167 Collections
.sort(p2d
);
169 for (Point2D p
: p2d
) {
170 if (p
.x
< corner
.x
|| p
.x
== corner
.x
&& p
.y
< corner
.y
)
174 for (int i
= 0; i
< p2d
.size(); ++i
)
175 if (p2d
.get(i
) == corner
)
177 List
<Point2D
> hull
= new ArrayList
<Point2D
>();
178 for (int i
= 0; i
<= p2d
.size(); ++i
) {
179 hull
.add(p2d
.get((start
+ i
) % p2d
.size()));
180 while (hull
.size() >= 3) {
181 Point2D a
= hull
.get(hull
.size() - 3);
182 Point2D b
= hull
.get(hull
.size() - 2);
183 Point2D c
= hull
.get(hull
.size() - 1);
184 /*if ((b.x - a.x) * (c.y - b.y) - (b.y - a.y) * (c.x - b.x) == 0 && (b.x - a.x) * (c.x - b.x) + (b.y - a.y) * (c.y - b.y) < 0)
185 throw new RuntimeException();*/
186 if ((b
.x
- a
.x
) * (c
.y
- b
.y
) - (b
.y
- a
.y
) * (c
.x
- b
.x
) <= 0)
187 hull
.remove(hull
.size() - 2);
193 for (int i
= 0; i
< hull
.size() - 1; ++i
) {
194 Point2D a
= hull
.get(i
);
195 Point2D b
= hull
.get(i
+ 1);
196 area
+= (a
.y
+ b
.y
) * (a
.x
- b
.x
);
197 if (i
< hull
.size() - 2) {
198 Point2D c
= hull
.get(i
+ 2);
199 if ((b
.x
- a
.x
) * (c
.y
- b
.y
) - (b
.y
- a
.y
) * (c
.x
- b
.x
) <= 0)
200 throw new RuntimeException();
204 throw new RuntimeException();
208 public double getDistance(Point center
) {
209 double res
= Double
.MAX_VALUE
;
210 for (int i1
= 0; i1
< points
.length
; ++i1
)
211 for (int i2
= i1
+ 1; i2
< points
.length
; ++i2
)
212 for (int i3
= i2
+ 1; i3
< points
.length
; ++i3
) {
213 Plane plane
= new Plane(points
[i1
], points
[i2
], points
[i3
]);
214 boolean[] was
= new boolean[3];
215 for (Point p
: points
)
216 was
[plane
.side(p
) + 1] = true;
217 if (was
[0] && was
[2])
219 res
= Math
.min(res
, Math
.abs(plane
.sideDouble(center
)));
224 public void rotateXY(double v
) {
225 for (Point p
: points
)
230 Polyhedron
parsePolyhedron() throws IOException
{
232 Polyhedron p
= new Polyhedron();
233 p
.points
= new Point
[n
];
234 for (int i
= 0; i
< n
; ++i
) {
238 p
.points
[i
] = new Point(x
, y
, z
);
243 private void solve() throws IOException
{
244 Polyhedron
[] polyhedrons
= new Polyhedron
[2];
245 for (int i
= 0; i
< 2; ++i
) {
246 polyhedrons
[i
] = parsePolyhedron();
247 /*polyhedrons[i].rotateXY(0.54326);
248 polyhedrons[i].swapXZ();
249 polyhedrons[i].rotateXY(0.1324543);
250 polyhedrons[i].swapXZ();
251 polyhedrons[i].rotateXY(0.5416512);*/
254 for (Polyhedron polyhedron
: polyhedrons
) {
255 double volume
= polyhedron
.integrate(new double[]{1});
256 double xc
= polyhedron
.integrate(new double[]{0, 1}) / volume
;
258 double yc
= polyhedron
.integrate(new double[]{0, 1}) / volume
;
261 double zc
= polyhedron
.integrate(new double[]{0, 1}) / volume
;
263 System
.out
.println("Center of mass: (" + xc
+ ", " + yc
+ ", " + zc
+ ")");
264 res
+= polyhedron
.getDistance(new Point(xc
, yc
, zc
));
270 public static void main(String
[] args
) throws InterruptedException
{
271 Thread thread
= new Thread(new asteroids_petr());
274 System
.err
.println(count
);
277 static final String TASK_ID
= "asteroids";
278 static final String IN_FILE
= TASK_ID
+ ".in";
279 static final String OUT_FILE
= TASK_ID
+ ".out";
280 BufferedReader reader
;
281 StringTokenizer tokenizer
;
286 reader
= new BufferedReader(new FileReader(IN_FILE
));
288 writer
= new PrintWriter(OUT_FILE
);
292 } catch (Exception e
) {
298 int nextInt() throws IOException
{
299 return Integer
.parseInt(nextToken());
302 long nextLong() throws IOException
{
303 return Long
.parseLong(nextToken());
306 double nextDouble() throws IOException
{
307 return Double
.parseDouble(nextToken());
310 String
nextToken() throws IOException
{
311 while (tokenizer
== null || !tokenizer
.hasMoreTokens()) {
312 tokenizer
= new StringTokenizer(reader
.readLine());
314 return tokenizer
.nextToken();