kb84tkhrのブログ

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

CGL_4_A: Convex Hull 続き2

忘れすぎてるので、なにやってたかだけでもおさらいする
pはPoint、vはVector、sはSegment、lはLine、cはCircle、PはPolygon
PointとVector、SegmentとLineは同じ型なので雰囲気で使い分け

型:Point, Vector, Segment, Line, Circle, Polygon
極座標:polar(a, r) -> p, p.arg()
ベクトルの基本演算: v1 + v2, v1 - v2, k * v (スカラー倍), v / k
ベクトルの大きさ: v.norm(), v.abs()
ベクトルの比較: v1 < v2, v1 == v2
内積(|a||b|cosθ): v1.dot(v2)
外積(ax*by-ay*bx):v1.cross(v2)
平行:v1.is_parallel(v2), l1.is_parallel(s2)
直行:v1.is_orthogonal(v2), l1.is_orthogonal(l2)
射影:l.projection(p)
反射:l.reflection(p)
点から直線への距離:p.distance_to_line(l)
点から線分への距離:p.distance_to_segment(s)
線分間の距離:s1.distance_with_segment(s2)
点と線分の位置関係(時計回り・反時計回り・・・):p.location(s)
線分同士の交差判定:s1.intersects(s2)
線分の交点:s1.intersection(s2)
円と直線の交点:c.cross_point_line(l)
円同士の交点:c1.cross_point_circle(c2)
点の内包: pl.contains(p)

アルゴリズムまでは見直していない

で書いてみたら
おさらいしたけど実際使ったのは差と外積くらいだった
だいたい素直に書けたという感覚
[-1]しているのは重複を避けるため

def half_hull(P):
    S = []
    S.append(P[0])
    S.append(P[1])
    for i in range(2, n):
        while len(S) > 1:
            if (S[-1] - S[-2]).cross(P[i] - S[-1]) >= 0:
                break
            S.pop()
        S.append(P[i])
    return S

n = int(input())
P = []
for i in range(n):
    x, y = [int(x) for x in input().split()]
    P.append(Point(x, y))

A = half_hull(sorted(P, key=lambda p: (p.y, p.x)))[:-1] + \
    half_hull(sorted(P, key=lambda p: (p.y, p.x), reverse=True))[:-1]

print(len(A), *A, sep='\n')

AC

ヒントの矢印はX座標最小の点から始まってるけど、
求められてる解答はY座標最小の点から出力することになってるから
そこはヒントに逆らった

ソートも使ったしスタックも使ったし、行き帰りで2回やってるし
これはきっとテキストの解に近いのでは
S[-2]とかやっててスタックかよというツッコミはなしで

では見比べる

  • スタックではなくPolygonを使っている
  • 外積ではなくてccwを使っている
  • ソートは1回

ほとんど同じだな(ということにしておこう
アンドリューのアルゴリズムと呼ぶ