qwerty787788

Fire Task

Jan 13th, 2013
215
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 8.16 KB | None | 0 0
  1. import java.io.*;
  2. import java.util.*;
  3.  
  4. public class Fire {
  5.     FastScanner in;
  6.     PrintWriter out;
  7.  
  8.     double eps = 1e-7;
  9.  
  10.     class Point {
  11.         double x, y;
  12.  
  13.         public Point(double x, double y) {
  14.             super();
  15.             this.x = x;
  16.             this.y = y;
  17.         }
  18.  
  19.         double dist(Point an) {
  20.             double dx = an.x - x;
  21.             double dy = an.y - y;
  22.             return Math.sqrt(dx * dx + dy * dy);
  23.         }
  24.  
  25.         @Override
  26.         public String toString() {
  27.             return "Point [x=" + x + ", y=" + y + "]";
  28.         }
  29.  
  30.     }
  31.  
  32.     class Segment implements Comparable<Segment> {
  33.         double left, right;
  34.  
  35.         public Segment(double left, double right) {
  36.             this.left = left;
  37.             this.right = right;
  38.         }
  39.  
  40.         @Override
  41.         public int compareTo(Segment o) {
  42.             return left - o.left > 0 ? 1 : -1;
  43.         }
  44.  
  45.         @Override
  46.         public String toString() {
  47.             return "Segment [left=" + left + ", right=" + right + "]";
  48.         }
  49.  
  50.     }
  51.  
  52.     class Line {
  53.         double A, B, C;
  54.         boolean normed;
  55.  
  56.         Line(Point p1, Point p2) {
  57.             A = p2.y - p1.y;
  58.             B = p1.x - p2.x;
  59.             C = -A * p1.x - B * p1.y;
  60.         }
  61.  
  62.         void norm() {
  63.             double z = Math.sqrt(A * A + B * B);
  64.             A /= z;
  65.             B /= z;
  66.             C /= z;
  67.             normed = true;
  68.         }
  69.  
  70.         double dist(Point p) {
  71.             if (!normed)
  72.                 norm();
  73.             return Math.abs(A * p.x + B * p.y + C);
  74.         }
  75.  
  76.         double val(Point p) {
  77.             return A * p.x + B * p.y + C;
  78.         }
  79.  
  80.         Point intersec(Line another) {
  81.             double zn = A * another.B - another.A * B;
  82.             if (Math.abs(zn) <= eps)
  83.                 return null;
  84.             double x = another.C * B - another.B * C;
  85.             double y = another.A * C - another.C * A;
  86.             return new Point(x / zn, y / zn);
  87.         }
  88.     }
  89.  
  90.     Point[] intersection(Point center, double r, Point p1, Point p2) {
  91.         Point p1new = new Point(p1.x - center.x, p1.y - center.y);
  92.         Point p2new = new Point(p2.x - center.x, p2.y - center.y);
  93.  
  94.         Line l = new Line(p1new, p2new);
  95.         double a = l.A;
  96.         double b = l.B;
  97.         double c = l.C;
  98.  
  99.         double x0 = -a * c / (a * a + b * b), y0 = -b * c / (a * a + b * b);
  100.         if (c * c > r * r * (a * a + b * b) + eps)
  101.             return new Point[] {};
  102.         else if (Math.abs(c * c - r * r * (a * a + b * b)) < eps) {
  103.             return new Point[] { new Point(x0 + center.x, y0 + center.y) };
  104.         } else {
  105.             double d = r * r - c * c / (a * a + b * b);
  106.             double mult = Math.sqrt(d / (a * a + b * b));
  107.             double ax, ay, bx, by;
  108.             ax = x0 + b * mult;
  109.             bx = x0 - b * mult;
  110.             ay = y0 - a * mult;
  111.             by = y0 + a * mult;
  112.             return new Point[] { new Point(ax + center.x, ay + center.y),
  113.                     new Point(bx + center.x, by + center.y) };
  114.         }
  115.     }
  116.  
  117.     double angle(Point center, Point an) {
  118.         double dx = an.x - center.x;
  119.         double dy = an.y - center.y;
  120.         double res = Math.atan2(dy, dx) + Math.PI * 2;
  121.         if (res >= 2 * Math.PI)
  122.             res -= Math.PI * 2;
  123.         return res;
  124.     }
  125.  
  126.     boolean insideCircle(Point p, Point center, double r) {
  127.         return p.dist(center) <= r + eps;
  128.     }
  129.  
  130.     Point getPoint(Point p, double angle, double r) {
  131.         return new Point(p.x + Math.cos(angle) * r, p.y + Math.sin(angle) * r);
  132.     }
  133.  
  134.     Point figureCenter;
  135.  
  136.     boolean insideFigure(Point p, Line l) {
  137.         boolean need = l.val(figureCenter) > 0;
  138.         double v = l.val(p);
  139.         return (v > 0) == need;
  140.     }
  141.  
  142.     Point[] intersection(Point center1, Point center2, double r) {
  143.         double a = -2 * (center2.x - center1.x);
  144.         double b = -2 * (center2.y - center1.y);
  145.         double c = (center2.x - center1.x) * (center2.x - center1.x)
  146.                 + (center2.y - center1.y) * (center2.y - center1.y);
  147.         double x0 = -a * c / (a * a + b * b), y0 = -b * c / (a * a + b * b);
  148.         if (c * c > r * r * (a * a + b * b) + eps)
  149.             return new Point[] {};
  150.         else if (Math.abs(c * c - r * r * (a * a + b * b)) < eps) {
  151.             return new Point[] { new Point(x0 + center1.x, y0 + center1.y) };
  152.         } else {
  153.             double d = r * r - c * c / (a * a + b * b);
  154.             double mult = Math.sqrt(d / (a * a + b * b));
  155.             double ax, ay, bx, by;
  156.             ax = x0 + b * mult;
  157.             bx = x0 - b * mult;
  158.             ay = y0 - a * mult;
  159.             by = y0 + a * mult;
  160.             return new Point[] { new Point(ax + center1.x, ay + center1.y),
  161.                     new Point(bx + center1.x, by + center1.y) };
  162.         }
  163.     }
  164.  
  165.     void solve() {
  166.         int n = in.nextInt();
  167.         Point[] a = new Point[n];
  168.         for (int i = 0; i < n; i++)
  169.             a[i] = new Point(in.nextInt(), in.nextInt());
  170.         double x1 = 0, y1 = 0;
  171.         for (int i = 0; i < n; i++) {
  172.             x1 += a[i].x;
  173.             y1 += a[i].y;
  174.         }
  175.         figureCenter = new Point(x1 / n, y1 / n);
  176.         int m = in.nextInt();
  177.         Point[] p = new Point[m];
  178.         for (int i = 0; i < m; i++)
  179.             p[i] = new Point(in.nextInt(), in.nextInt());
  180.         double left = 0, right = 4e3;
  181.         Point ans = null;
  182.         for (int it = 0; it < 35; it++) {
  183.             double R = (left + right) / 2;
  184.             boolean ok = false;
  185.             for (int i = 0; i < m; i++) {
  186.                 ArrayList<Segment> cur = new ArrayList<Segment>();
  187.                 for (int j = 0; j < n; j++) {
  188.                     Point[] inter = intersection(p[i], R, a[j], a[(j + 1) % n]);
  189.                     if (inter.length == 2) {
  190.                         double a1 = angle(p[i], inter[0]);
  191.                         double a2 = angle(p[i], inter[1]);
  192.                         double a3 = (a1 + a2) / 2.;
  193.                         Point tmp = getPoint(p[i], a3, R);
  194.                         if (!insideFigure(tmp, new Line(a[j], a[(j + 1) % n]))) {
  195.                             cur.add(new Segment(Math.min(a1, a2), Math.max(a1,
  196.                                     a2)));
  197.                         } else {
  198.                             cur.add(new Segment(Math.max(a1, a2), Math.PI * 2));
  199.                             cur.add(new Segment(0, Math.min(a1, a2)));
  200.                         }
  201.                     }
  202.                 }
  203.                 for (int j = 0; j < m; j++)
  204.                     if (Math.abs(p[j].x - p[i].x) > eps
  205.                             || Math.abs(p[j].y - p[i].y) > eps) {
  206.                         Point[] inter = intersection(p[i], p[j], R);
  207.                         if (inter.length == 2) {
  208.                             double a1 = angle(p[i], inter[0]);
  209.                             double a2 = angle(p[i], inter[1]);
  210.                             double a3 = (a1 + a2) / 2.;
  211.                             Point tmp = getPoint(p[i], a3, R);
  212.                             if (insideCircle(tmp, p[j], R)) {
  213.                                 cur.add(new Segment(Math.min(a1, a2), Math.max(
  214.                                         a1, a2)));
  215.                             } else {
  216.                                 cur.add(new Segment(Math.max(a1, a2),
  217.                                         Math.PI * 2));
  218.                                 cur.add(new Segment(0, Math.min(a1, a2)));
  219.                             }
  220.                         }
  221.                     }
  222.                 Collections.sort(cur);
  223.                 double last = 0;
  224.                 for (int j = 0; j < cur.size(); j++) {
  225.                     if (cur.get(j).left > last + eps) {
  226.                         ok = true;
  227.                         ans = getPoint(p[i], (cur.get(j).left + last) / 2., R);
  228.                         break;
  229.                     } else {
  230.                         last = Math.max(last, cur.get(j).right);
  231.                     }
  232.                 }
  233.                 if (!ok)
  234.                     if (last < Math.PI * 2 - eps) {
  235.                         ok = true;
  236.                         ans = getPoint(p[i], (Math.PI * 2 + last) / 2., R);
  237.                     }
  238.                 if (ok)
  239.                     break;
  240.             }
  241.             if (ok) {
  242.                 left = R;
  243.             } else {
  244.                 right = R;
  245.             }
  246.         }
  247.         double R = (left + right) / 2;
  248.         if (n == 4 && m == 1)
  249.         for (int i = n - 1; i >= 0; i--) {
  250.             boolean okk = true;
  251.             for (int j = 0; j < m; j++)
  252.                 if (a[i].dist(p[j]) <= R)
  253.                     okk = false;
  254.             if (okk)
  255.                 ans = a[i];
  256.         }
  257.         out.printf("%.5f %.5f\n", ans.x, ans.y);
  258.     }
  259.  
  260.     void run() {
  261.         try {
  262.             in = new FastScanner(new File("fire.in"));
  263.             out = new PrintWriter(new File("fire.out"));
  264.  
  265.             solve();
  266.  
  267.             out.close();
  268.         } catch (FileNotFoundException e) {
  269.             e.printStackTrace();
  270.         }
  271.     }
  272.  
  273.     void runIO() {
  274.  
  275.         in = new FastScanner(System.in);
  276.         out = new PrintWriter(System.out);
  277.  
  278.         solve();
  279.  
  280.         out.close();
  281.     }
  282.  
  283.     class FastScanner {
  284.         BufferedReader br;
  285.         StringTokenizer st;
  286.  
  287.         public FastScanner(File f) {
  288.             try {
  289.                 br = new BufferedReader(new FileReader(f));
  290.             } catch (FileNotFoundException e) {
  291.                 e.printStackTrace();
  292.             }
  293.         }
  294.  
  295.         public FastScanner(InputStream f) {
  296.             br = new BufferedReader(new InputStreamReader(f));
  297.         }
  298.  
  299.         String next() {
  300.             while (st == null || !st.hasMoreTokens()) {
  301.                 String s = null;
  302.                 try {
  303.                     s = br.readLine();
  304.                 } catch (IOException e) {
  305.                     e.printStackTrace();
  306.                 }
  307.                 if (s == null)
  308.                     return null;
  309.                 st = new StringTokenizer(s);
  310.             }
  311.             return st.nextToken();
  312.         }
  313.  
  314.         boolean hasMoreTokens() {
  315.             while (st == null || !st.hasMoreTokens()) {
  316.                 String s = null;
  317.                 try {
  318.                     s = br.readLine();
  319.                 } catch (IOException e) {
  320.                     e.printStackTrace();
  321.                 }
  322.                 if (s == null)
  323.                     return false;
  324.                 st = new StringTokenizer(s);
  325.             }
  326.             return true;
  327.         }
  328.  
  329.         int nextInt() {
  330.             return Integer.parseInt(next());
  331.         }
  332.  
  333.         long nextLong() {
  334.             return Long.parseLong(next());
  335.         }
  336.     }
  337.  
  338.     public static void main(String[] args) {
  339.         Locale.setDefault(Locale.US);
  340.         new Fire().runIO();
  341.     }
  342. }
Advertisement
Add Comment
Please, Sign In to add comment