Problem: Brothers Fred and George Weasley once got into the sporting goods store and opened a box of Quidditch balls. After long and painful experiments they found out that the Golden Snitch is not enchanted at all. It is simply a programmed device. It always moves along the same trajectory, which is a polyline with vertices at the points (x0, y0, z0), (x1, y1, z1), ..., (xn, yn, zn). At the beginning of the game the snitch is positioned at the point (x0, y0, z0), and then moves along the polyline at the constant speed vs. The twins have not yet found out how the snitch behaves then. Nevertheless, they hope that the retrieved information will help Harry Potter and his team in the upcoming match against Slytherin. Harry Potter learned that at the beginning the game he will be at the point (Px, Py, Pz) and his super fast Nimbus 2011 broom allows him to move at the constant speed vp in any direction or remain idle. vp is not less than the speed of the snitch vs. Harry Potter, of course, wants to catch the snitch as soon as possible. Or, if catching the snitch while it is moving along the polyline is impossible, he wants to hurry the Weasley brothers with their experiments. Harry Potter catches the snitch at the time when they are at the same point. Help Harry.

Input

The first line contains a single integer n (1 ≤ n ≤ 10000). The following n + 1 lines contain the coordinates xi, yi, zi, separated by single spaces. The coordinates of any two consecutive points do not coincide. The next line contains the velocities vp and vs, the last line contains Px, Py, Pz, separated by single spaces. All the numbers in the input are integers, their absolute value does not exceed 104. The speeds are strictly positive. It is guaranteed that vs ≤ vp.

Output

If Harry Potter can catch the snitch while it is moving along the polyline (including the end (xn, yn, zn)), print "YES" in the first line (without the quotes). Print in the second line t, which is the earliest moment of time, when Harry will be able to catch the snitch. On the third line print three numbers X, Y, Z, the coordinates of the point at which this happens. The absolute or relative error in the answer should not exceed 10 - 6. If Harry is not able to catch the snitch during its moving along the described polyline, print "NO".

Examples

Input

4
0 0 0
0 10 0
10 10 0
10 0 0
0 0 0
1 1
5 5 25


Output

YES
25.5000000000
10.0000000000 4.5000000000 0.0000000000


Input

4
0 0 0
0 10 0
10 10 0
10 0 0
0 0 0
1 1
5 5 50


Output

NO


Input

1
1 2 3
4 5 6
20 10
1 2 3


Output

YES
0.0000000000
1.0000000000 2.0000000000 3.0000000000

Solution (in JAVA):

Solution:

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import static java.lang.Math.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.PriorityQueue;
import java.util.Stack;
import java.util.StringTokenizer;
import java.util.logging.Logger;

/**
 *
 * @author pttrung
 */
public class C {

    public static long Mod = 1000000007;
    public static double Epsilon = 1e-5;

    public static void main(String[] args) {
        try {
            Scanner in = new Scanner();
            PrintWriter out = new PrintWriter(System.out);
            int n = in.nextInt();
            Point3D[] data = new Point3D[n + 1];

            for (int i = 0; i < data.length; i++) {
                data[i] = new Point3D(in.nextInt(), in.nextInt(), in.nextInt());
            }
            int vp = in.nextInt();
            int vs = in.nextInt();

            Point3D p = new Point3D(in.nextInt(), in.nextInt(), in.nextInt());
            double[] dist = new double[n + 1];
            // System.out.println(distance(p, data[0]));
            for (int i = 1; i < data.length; i++) {
                dist[i] = dist[i - 1] + distance(data[i], data[i - 1]);
                //   System.out.println(distance(p, data[i]));
            }
            boolean found = false;
            for (int i = 1; i < dist.length && !found; i++) {


                //  Point3D center = join(0.5, data[i], data[i - 1]);
                //    System.out.println("Start");
                if (dist[i] * vp / vs >= distance(p, data[i])) {
                    //out.println("INDEX " + i);
                    Point3D l = data[i - 1];
                    Point3D r = data[i];
                    while (Math.abs(distance(l, r)) > 1e-9) {
                        //double mid = (end + start) / 2;
                        Point3D temp = join(0.5, l, r);
                        // System.out.println("Point " + temp);
                        //double a = distance(temp, p) / vp;
                        double cur = distance(temp, p);
                        double b = (distance(temp, data[i - 1]) + dist[i - 1]) / vs;
                        double val = b * vp;
                        // System.out.println(a + " " + b);
                        if (cur > val) {
                            l = temp;
                        } else {
                            r = temp;
                        }

                    }
                    double b = (distance(l, data[i - 1]) + dist[i - 1]) / vs;
                    double a = distance(p, l) / vp;
                    if (a >= b) {
                        found = true;
                        out.println("YES");
                        out.println(b);
                        out.println(l);
                    }
                }

//              
            }
            if (!found) {
                out.println("NO");
            }
            out.close();
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }

    static Point3D join(double rate, Point3D a, Point3D b) {
        double x = rate * (a.x + b.x);
        double y = rate * (a.y + b.y);
        double z = rate * (a.z + b.z);
        return new Point3D(x, y, z);
    }

    static double distance(Point3D a, Point3D b) {
        double val = (a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y) + (a.z - b.z) * (a.z - b.z);
        return Math.sqrt(val);
    }

    static class Point3D {

        double x, y, z;

        public Point3D(int x, int y, int z) {
            this.x = x;
            this.y = y;
            this.z = z;
        }

        public Point3D(double x, double y, double z) {
            this.x = x;
            this.y = y;
            this.z = z;
        }

        public String toString() {
            return x + " " + y + " " + z;
        }
    }

    public static double squareDistance(Point a, Point b) {
        return (a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y);
    }

    public static long pow(int a, int b) {
        if (b == 0) {
            return 1;
        }
        long val = pow(a, b / 2);
        if (b % 2 == 0) {
            return val * val % Mod;
        } else {
            return a * val * val % Mod;
        }
    }

    public static long gcd(long a, long b) {
        if (b == 0) {
            return a;
        }
        return gcd(b, a % b);
    }

    static class Line {

        double a, b, c;

        Line(double x1, double y1, double x2, double y2) {
            if (Math.abs(x1 - x2) < Epsilon && Math.abs(y1 - y2) < Epsilon) {
                throw new RuntimeException("Two point are the same");
            }
            a = y1 - y2;
            b = x2 - x1;
            c = -a * x1 - b * y1;
        }

        Line(Point x, Point y) {
            this(x.x, x.y, y.x, y.y);
        }

        public Line perpendicular(Point p) {
            return new Line(p, new Point(p.x + a, p.y + b));
        }

        public Point intersect(Line l) {
            double d = a * l.b - b * l.a;
            if (d == 0) {
                throw new RuntimeException("Two lines are parallel");
            }

            return new Point((l.c * b - c * l.b) / d, (l.a * c - l.c * a) / d);
        }
    }

    static void check(Point a, Point b, ArrayList<Point> p, Point[] rec, int index) {
        for (int i = 0; i < 4; i++) {
            int m = (i + index) % 4;
            int j = (i + 1 + index) % 4;
            Point k = intersect(minus(b, a), minus(rec[m], rec[j]), minus(rec[m], a));
            if (k.x >= 0 && k.x <= 1 && k.y >= 0 && k.y <= 1) {
                Point val = new Point(k.x * minus(b, a).x, k.x * minus(b, a).y);
                p.add(add(val, a));
                // System.out.println(a + " " + b + " " + rec[i] + " " + rec[j]);
                // System.out.println(add(val, a));
            }
        }
    }

    static Point intersect(Point a, Point b, Point c) {
        double D = cross(a, b);
        if (D != 0) {
            return new Point(cross(c, b) / D, cross(a, c) / D);
        }
        return null;
    }

    static Point convert(Point a, double angle) {
        double x = a.x * cos(angle) - a.y * sin(angle);
        double y = a.x * sin(angle) + a.y * cos(angle);
        return new Point(x, y);
    }

    static Point minus(Point a, Point b) {
        return new Point(a.x - b.x, a.y - b.y);
    }

    static Point add(Point a, Point b) {
        return new Point(a.x + b.x, a.y + b.y);
    }

    static double cross(Point a, Point b) {
        return a.x * b.y - a.y * b.x;
    }

    static class Point {

        double x, y;

        Point(double x, double y) {
            this.x = x;
            this.y = y;
        }

        @Override
        public String toString() {
            return "Point: " + x + " " + y;
        }
    }

    static class Scanner {

        BufferedReader br;
        StringTokenizer st;

        public Scanner() {
            // System.setOut(new PrintStream(new BufferedOutputStream(System.out), true));
            br = new BufferedReader(new InputStreamReader(System.in));
        }

        public String next() {

            while (st == null || !st.hasMoreTokens()) {
                try {
                    st = new StringTokenizer(br.readLine());
                } catch (Exception e) {
                    throw new RuntimeException();
                }
            }
            return st.nextToken();
        }

        public long nextLong() {
            return Long.parseLong(next());
        }

        public int nextInt() {
            return Integer.parseInt(next());
        }

        public double nextDouble() {
            return Double.parseDouble(next());
        }

        public String nextLine() {
            st = null;
            try {
                return br.readLine();
            } catch (Exception e) {
                throw new RuntimeException();
            }
        }

        public boolean endLine() {
            try {
                String next = br.readLine();
                while (next != null && next.trim().isEmpty()) {
                    next = br.readLine();
                }
                if (next == null) {
                    return true;
                }
                st = new StringTokenizer(next);
                return st.hasMoreTokens();
            } catch (Exception e) {
                throw new RuntimeException();
            }
        }
    }
}