roiti46's blog

主に競プロ問題の解説を載せてます

yukicoder No.199 星を描こう

もっこく!どこくすい!…

問題はこちら

問題

平面上の互いに重ならない点を5つ与えられる。この5つの点を結んで五芒星を作れるかどうか答えよ。

解法

与えられた点が凸包を形成するなら五芒星を作れる。
任意の3つの点を結んでできる三角形の周または内部にほかの2点が存在しなければ凸包と判定できる。順列の計算が必要だが、点が5個しかないのでこの方法でも間に合う。

三角形と点の位置関係は、頂点と点を結んでできる図形と三角形の面積を比べることで判定している。

import itertools as it
XY = [map(int, raw_input().split()) for i in xrange(5)]
for i, j, k, l in it.permutations(xrange(5), 4):
    (x1,y1), (x2,y2), (x3,y3), (xp,yp) = XY[i], XY[j], XY[k], XY[l]

    def S(x1, y1, x2, y2, x3 = xp, y3 = yp):
        return abs(x1 * (y2 - y3) + x2 * (y3 - y1) + x3 * (y1 - y2)) / 2.0
        
    if S(x1,y1,x2,y2) + S(x1,y1,x3,y3) + S(x3,y3,x2,y2) - S(x1,y1,x2,y2,x3,y3) < 0.0000001:
        print "NO"
        break
else:
    print "YES"

まとめ

ほかにもいろいろな解き方がありそうな問題。
点と三角形の位置関係はAOJで解いたのが記憶によく残ってる(このコードもその解答の再利用)