|
@@ -3,6 +3,7 @@ package main
|
|
|
import (
|
|
|
"bufio"
|
|
|
"fmt"
|
|
|
+ "math"
|
|
|
"os"
|
|
|
"strconv"
|
|
|
"strings"
|
|
@@ -14,24 +15,63 @@ func readInt(s *bufio.Scanner) int {
|
|
|
return int(i)
|
|
|
}
|
|
|
|
|
|
-func read5Float32(s *bufio.Scanner) (float32, float32, float32, float32, float32) {
|
|
|
+func read5Float64(s *bufio.Scanner) (float64, float64, float64, float64, float64) {
|
|
|
s.Scan()
|
|
|
n := strings.Split(s.Text(), " ")
|
|
|
- n1, _ := strconv.ParseFloat(n[0], 32)
|
|
|
- n2, _ := strconv.ParseFloat(n[1], 32)
|
|
|
- n3, _ := strconv.ParseFloat(n[2], 32)
|
|
|
- n4, _ := strconv.ParseFloat(n[3], 32)
|
|
|
- n5, _ := strconv.ParseFloat(n[4], 32)
|
|
|
- return float32(n1), float32(n2), float32(n3), float32(n4), float32(n5)
|
|
|
+ n1, _ := strconv.ParseFloat(n[0], 64)
|
|
|
+ n2, _ := strconv.ParseFloat(n[1], 64)
|
|
|
+ n3, _ := strconv.ParseFloat(n[2], 64)
|
|
|
+ n4, _ := strconv.ParseFloat(n[3], 64)
|
|
|
+ n5, _ := strconv.ParseFloat(n[4], 64)
|
|
|
+ return n1, n2, n3, n4, n5
|
|
|
}
|
|
|
|
|
|
-func hitFly(scanner *bufio.Scanner) []float32 {
|
|
|
+func circularSegment(r, theta float64) float64 {
|
|
|
+ return r * r * (theta - math.Sin(theta)) / 2
|
|
|
+}
|
|
|
+
|
|
|
+func hitFly(scanner *bufio.Scanner) []float64 {
|
|
|
caseCnt := readInt(scanner)
|
|
|
+ answer := make([]float64, caseCnt)
|
|
|
for i := 0; i < caseCnt; i++ {
|
|
|
- f, R, t, r, g := read5Float32(scanner)
|
|
|
-
|
|
|
+ // r fly, r outer ring, thickness, r string and gap length
|
|
|
+ f, R, t, r, g := read5Float64(scanner)
|
|
|
+ if g <= 2*f {
|
|
|
+ answer[i] = 1.
|
|
|
+ continue
|
|
|
+ }
|
|
|
+ rad := R - t - f
|
|
|
+ sqrRad := rad * rad
|
|
|
+ gridArea := (g - 2*f) * (g - 2*f)
|
|
|
+ area := 0.
|
|
|
+ for x1 := r + f; x1 < rad; x1 += g + 2*r { // 1st quadrant, x1, y1 is the coord of br
|
|
|
+ for y1 := r + f; y1 < rad; y1 += g + 2*r {
|
|
|
+ x2, y2 := x1+g-2*f, y1+g-2*f
|
|
|
+ if x1*x1+y1*y1 >= sqrRad {
|
|
|
+ continue
|
|
|
+ }
|
|
|
+ switch {
|
|
|
+ case x2*x2+y2*y2 <= sqrRad: // All points inside circle
|
|
|
+ area += gridArea
|
|
|
+ case x1*x1+y2*y2 >= sqrRad && x2*x2+y1*y1 >= sqrRad:
|
|
|
+ // Only x1, y1 inside
|
|
|
+ area += circularSegment(rad, math.Pi/2-math.Asin(x1/rad)-math.Asin(y1/rad))
|
|
|
+ area += (math.Sqrt(sqrRad-x1*x1) - y1) * (math.Sqrt(sqrRad-y1*y1) - x1) / 2
|
|
|
+ case x1*x1+y2*y2 >= sqrRad: // x1, y1 and x2, y1 inside
|
|
|
+ area += circularSegment(rad, math.Acos(x1/rad)-math.Acos(x2/rad))
|
|
|
+ area += ((math.Sqrt(sqrRad-x1*x1) - y1) + (math.Sqrt(sqrRad-x2*x2) - y1)) * (x2 - x1) / 2
|
|
|
+ case x2*x2+y1*y1 >= sqrRad: // x1, y1 and x1, y2 inside
|
|
|
+ area += circularSegment(rad, math.Asin(y2/rad)-math.Asin(y1/rad))
|
|
|
+ area += ((math.Sqrt(sqrRad-y2*y2) - x1) + (math.Sqrt(sqrRad-y1*y1) - x1)) * (y2 - y1) / 2
|
|
|
+ default: // All except x2, y2 inside
|
|
|
+ area += circularSegment(rad, math.Asin(y2/rad)-math.Acos(x2/rad))
|
|
|
+ area += gridArea - (x2-math.Sqrt(sqrRad-y2*y2))*(y2-math.Sqrt(sqrRad-x2*x2))/2
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ answer[i] = 1. - area/(math.Pi*R*R/4)
|
|
|
}
|
|
|
- return []float32{}
|
|
|
+ return answer
|
|
|
}
|
|
|
|
|
|
func main() {
|
|
@@ -43,7 +83,7 @@ func main() {
|
|
|
test
|
|
|
)
|
|
|
|
|
|
- fileType := test
|
|
|
+ fileType := large
|
|
|
|
|
|
fin, _ := os.Open(inputFiles[fileType])
|
|
|
defer fin.Close()
|