← Home
package main

import (
	"bufio"
	"fmt"
	"math"
	"os"
)

type Point struct {
	x, y float64
}

func cross(a, b Point) float64 {
	return a.x*b.y - a.y*b.x
}

func sub(a, b Point) Point {
	return Point{a.x - b.x, a.y - b.y}
}

func dist(a, b Point) float64 {
	return math.Hypot(a.x-b.x, a.y-b.y)
}

func lineIntersection(p1, v1, p2, v2 Point) (Point, bool) {
	c := cross(v1, v2)
	if math.Abs(c) < 1e-9 {
		return Point{}, false
	}
	diff := sub(p2, p1)
	t := cross(diff, v2) / c
	return Point{p1.x + t*v1.x, p1.y + t*v1.y}, true
}

func getTangents(V []Point, S Point) (int, int) {
	n := len(V)
	sign := func(i int) bool {
		return cross(sub(V[i], S), sub(V[(i+1)%n], S)) > 0
	}

	s0 := sign(0)
	findTransition := func(target bool) int {
		l, r := 1, n-1
		ans := 0
		for l <= r {
			mid := (l + r) / 2
			if sign(mid) == s0 {
				if s0 == target {
					ans = mid
					l = mid + 1
				} else {
					l = mid + 1
				}
			} else {
				if s0 == target {
					r = mid - 1
				} else {
					ans = mid
					r = mid - 1
				}
			}
		}
		return ans
	}

	t1 := findTransition(s0)
	t2 := findTransition(!s0)

	var left, right int
	if s0 {
		left = t1
		right = t2
	} else {
		right = t1
		left = t2
	}
	return (left + 1) % n, (right + 1) % n
}

func insideAngle(S, VR, VL, E Point) bool {
	c1 := cross(sub(VR, S), sub(E, S))
	c2 := cross(sub(E, S), sub(VL, S))
	return c1 > 1e-9 && c2 > 1e-9
}

func solve() {
	scanner := bufio.NewScanner(os.Stdin)
	scanner.Split(bufio.ScanWords)

	readInt := func() int {
		scanner.Scan()
		var x int
		fmt.Sscanf(scanner.Text(), "%d", &x)
		return x
	}
	readFloat := func() float64 {
		scanner.Scan()
		var x float64
		fmt.Sscanf(scanner.Text(), "%f", &x)
		return x
	}

	if !scanner.Scan() {
		return
	}
	var n int
	fmt.Sscanf(scanner.Text(), "%d", &n)

	V := make([]Point, n)
	for i := 0; i < n; i++ {
		V[i] = Point{readFloat(), readFloat()}
	}

	q := readInt()
	for i := 0; i < q; i++ {
		S := Point{readFloat(), readFloat()}
		E := Point{readFloat(), readFloat()}

		sr, sl := getTangents(V, S)
		er, el := getTangents(V, E)

		V_SR, V_SL := V[sr], V[sl]
		V_ER, V_EL := V[er], V[el]

		if !(insideAngle(S, V_SR, V_SL, E) && insideAngle(E, V_ER, V_EL, S)) {
			fmt.Printf("%.9f\n", dist(S, E))
			continue
		}

		ans := math.Inf(1)

		p1, ok1 := lineIntersection(S, sub(V_SR, S), E, sub(V_EL, E))
		if ok1 {
			ans = math.Min(ans, dist(S, p1)+dist(p1, E))
		}

		p2, ok2 := lineIntersection(S, sub(V_SL, S), E, sub(V_ER, E))
		if ok2 {
			ans = math.Min(ans, dist(S, p2)+dist(p2, E))
		}

		if math.IsInf(ans, 1) {
			fmt.Println("-1")
		} else {
			fmt.Printf("%.9f\n", ans)
		}
	}
}

func main() {
	solve()
}