main.go 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101
  1. package main
  2. import (
  3. "bufio"
  4. "fmt"
  5. "math"
  6. "os"
  7. "strconv"
  8. "strings"
  9. )
  10. func readInt(s *bufio.Scanner) int {
  11. s.Scan()
  12. i, _ := strconv.ParseInt(s.Text(), 10, 32)
  13. return int(i)
  14. }
  15. func read5Float64(s *bufio.Scanner) (float64, float64, float64, float64, float64) {
  16. s.Scan()
  17. n := strings.Split(s.Text(), " ")
  18. n1, _ := strconv.ParseFloat(n[0], 64)
  19. n2, _ := strconv.ParseFloat(n[1], 64)
  20. n3, _ := strconv.ParseFloat(n[2], 64)
  21. n4, _ := strconv.ParseFloat(n[3], 64)
  22. n5, _ := strconv.ParseFloat(n[4], 64)
  23. return n1, n2, n3, n4, n5
  24. }
  25. func circularSegment(r, theta float64) float64 {
  26. return r * r * (theta - math.Sin(theta)) / 2
  27. }
  28. func hitFly(scanner *bufio.Scanner) []float64 {
  29. caseCnt := readInt(scanner)
  30. answer := make([]float64, caseCnt)
  31. for i := 0; i < caseCnt; i++ {
  32. // r fly, r outer ring, thickness, r string and gap length
  33. f, R, t, r, g := read5Float64(scanner)
  34. if g <= 2*f {
  35. answer[i] = 1.
  36. continue
  37. }
  38. rad := R - t - f
  39. sqrRad := rad * rad
  40. gridArea := (g - 2*f) * (g - 2*f)
  41. area := 0.
  42. for x1 := r + f; x1 < rad; x1 += g + 2*r { // 1st quadrant, x1, y1 is the coord of br
  43. for y1 := r + f; y1 < rad; y1 += g + 2*r {
  44. x2, y2 := x1+g-2*f, y1+g-2*f
  45. if x1*x1+y1*y1 >= sqrRad {
  46. continue
  47. }
  48. switch {
  49. case x2*x2+y2*y2 <= sqrRad: // All points inside circle
  50. area += gridArea
  51. case x1*x1+y2*y2 >= sqrRad && x2*x2+y1*y1 >= sqrRad:
  52. // Only x1, y1 inside
  53. area += circularSegment(rad, math.Pi/2-math.Asin(x1/rad)-math.Asin(y1/rad))
  54. area += (math.Sqrt(sqrRad-x1*x1) - y1) * (math.Sqrt(sqrRad-y1*y1) - x1) / 2
  55. case x1*x1+y2*y2 >= sqrRad: // x1, y1 and x2, y1 inside
  56. area += circularSegment(rad, math.Acos(x1/rad)-math.Acos(x2/rad))
  57. area += ((math.Sqrt(sqrRad-x1*x1) - y1) + (math.Sqrt(sqrRad-x2*x2) - y1)) * (x2 - x1) / 2
  58. case x2*x2+y1*y1 >= sqrRad: // x1, y1 and x1, y2 inside
  59. area += circularSegment(rad, math.Asin(y2/rad)-math.Asin(y1/rad))
  60. area += ((math.Sqrt(sqrRad-y2*y2) - x1) + (math.Sqrt(sqrRad-y1*y1) - x1)) * (y2 - y1) / 2
  61. default: // All except x2, y2 inside
  62. area += circularSegment(rad, math.Asin(y2/rad)-math.Acos(x2/rad))
  63. area += gridArea - (x2-math.Sqrt(sqrRad-y2*y2))*(y2-math.Sqrt(sqrRad-x2*x2))/2
  64. }
  65. }
  66. }
  67. answer[i] = 1. - area/(math.Pi*R*R/4)
  68. }
  69. return answer
  70. }
  71. func main() {
  72. inputFiles := []string{"C-small-practice.in", "C-large-practice.in", "test.in"}
  73. outputFiles := []string{"result-small.out", "result-large.out", "test.out"}
  74. const (
  75. small = iota
  76. large
  77. test
  78. )
  79. fileType := large
  80. fin, _ := os.Open(inputFiles[fileType])
  81. defer fin.Close()
  82. scanner := bufio.NewScanner(fin)
  83. answer := hitFly(scanner)
  84. fout, _ := os.Create(outputFiles[fileType])
  85. defer fout.Close()
  86. for i, ans := range answer {
  87. s := fmt.Sprintf("Case #%d: %f\n", i+1, ans)
  88. fout.WriteString(s)
  89. }
  90. }