kb84tkhrのブログ

何を書こうか考え中です あ、あと組織とは関係ないってやつです 個人的なやつ

CGL_7_D: Cross Points of a Circle and a Line

ふむ
円と直線の交点
学校でなら連立方程式を解きにかかるところだけど
ここではベクトルを使って解いていくようだからそっちで考える

ヒントは射影っぽい絵
まあやればできるよね
って印象

中心Oから直線への射影をA、一方の交点をBとするとOB = rで
あとABの距離を出して
ABは外積使って関数作ったけど、それを使うか
射影をすでに求めてたら三平方の定理で求めるか
どっちが楽かな
せっかく関数があるからまずはそっちでやるか
でAB方向の単位ベクトルaを作ってA+AB*a

できるけどなんかちょっとめんどくさく見えるなあ
連立方程式解くのと比べてどうだろう
解いた式を計算するだけならそっちのほうが楽そうに思える

ベクトルでやるにしてももっといい考え方がある?
まあいいやそのまま書く
こうな

class Circle:

    def cross_point(self, line: Line) -> List[Point]:
        proj = line.projection(self.c)
        dist = self.c.distance_to_line(line)
        tan = sqrt(self.r * self.r - dist * dist)
        u = line.vector() / line.vector().abs()
        return sorted([proj - tan * u, proj + tan * u])

x座標で並べ替えるのがこの関数の仕事かというと微妙な気もする

main

def main() -> None:
    cx, cy, r = [int(x) for x in input().split()]
    c = Circle(Point(cx, cy), r)
    q = int(input())

    for _ in range(q):
        x0, y0, x1, y1 = [int(x) for x in input().split()]
        line = Line(Point(x0, y0), Point(x1, y1))
        left, right = c.cross_point(line)
        print(left.x, left.y, right.x, right.y)

テスト2でWA
mjsk

回答がこれ

-0.43468860 -0.90058083 0.95192997 -0.30631573
-0.77700043 0.62950007 0.93916259 0.34347290
-0.84991694 -0.52691669 0.92050517 -0.39073037
-0.94804172 0.31814603 -0.63686394 -0.77097621
-0.24253563 0.97014250 0.24253563 -0.97014250
-0.31622777 -0.94868330 0.31622777 0.94868330
-0.32432432 -0.94594595 0.00000000 -1.00000000
0.26322452 -0.96473460 0.83266589 0.55377570

自分の実行結果がこれ

-0.43468859527183135 -0.9005808265450704 0.9519299745821757 -0.30631572517906747
-0.7770004252101379 0.6295000708683562 0.9391625873722993 0.3434729021046168
-0.849916939625135 -0.526916687663472 0.9205051749192524 -0.39073037116005754
-0.9480417217214212 0.318146026024974 -0.6368639386559374 -0.7709762147042192
-0.24253562503633297 0.9701425001453319 0.24253562503633297 -0.9701425001453319
-0.31622776601683794 -0.9486832980505138 0.31622776601683794 0.9486832980505138
-0.3243243243243234 -0.945945945945946 6.106226635438361e-16 -1.0
0.2632245247831982 -0.964734600578138 0.8326658861757059 0.5537756964685491

じー

106226635438361e-16

お前か
えーとこういう場合はstr.format()でフォーマットを指定するんだな
回答例と合わせるには{:.8f}
こうね

        print("{:.8f} {:.8f} {:.8f} {:.8f}".format(
            left.x, left.y, right.x, right.y))

AC
考え方も解説と同じ