사용자 도구

사이트 도구


ps:problems:boj:28067

기하가 너무 좋아

ps
링크acmicpc.net/…
출처BOJ
문제 번호28067
문제명기하가 너무 좋아
레벨골드 4
분류

기하학

시간복잡도O((nm)^2)
인풋사이즈n<=10, m<=10
사용한 언어Python 3.11
제출기록34400KB / 48ms
최고기록48ms
해결날짜2023/05/27

풀이

  • 범위가 작기 때문에, 모든 삼각형을 다 만들어보고, 그중에서 합동이 아닌 삼각형들의 갯수를 세는 나이브한 알고리즘도 충분히 돌아간다.
  • 모든 삼각형을 다 만들어 보는 간단한 방법은, 가능한 모든 세점 조합중에서, 세 점이 삼각형을 이루지 않는 경우만 제외하는 것이다.
    • 세 점이 삼각형을 이루지 않는 경우는, 세 점이 모두 한 직선상에 놓여있는 경우이다. 간단하게 확인하는 방법은 벡터곱을 이용해서 세점의 방향성을 체크하는 것이다.
  • 두 삼각형이 합동이 되는지를 확인하는 간단한 방법은, 세 변의 길이가 같은지를 확인하는 것이다 (SSS합동). 앞에서 찾은 모든 삼각형들에 대해서 3변의 길이를 계산해보고 중복되지 않는 것들만 남기면, 합동이 아닌 삼각형들의 갯수를 찾을수 있다.
  • 이 방식은 가능한 모든 세점의 조합에 대해서 처리해야 하므로 O({점의 갯수}^3)이 된다, 점의 갯수는 O(n*m)인데, n과 m이 모두 10 이하이므로 시간 내에 통과하기에는 충분하다. 그리고 공식 풀이에서도 이 방식을 소개한다
  • 하지만, 간단한 방법으로 시간을 좀 더 단축시킬 수 있다.
  • 직사각형 영역 안에 있는 모든 삼각형은, 적절하게 평행이동시키면 최소 한개의 꼭짓점이 직사각형의 꼭짓점에 오도록 만들수 있다. 그리고 대칭변환까지 시키면 한개의 꼭짓점이 원점에 오도록 만들수 있다.
  • 이것을 반대로 생각하면, 합동이 아닌 삼각형의 갯수를 세는 것은, 한개의 꼭짓점이 원점에 위치한 삼각형들에 대해서만 세어보는 것으로 충분하다는 것을 알수 있다. 하나의 점을 원점으로 고정시켰으므로, 나머지 두개의 점에 대해서만 모든 조합을 테스트하면 된다. 시간복잡도는 O({점의 갯수}^2)로 단축된다. 코드도 깔끔해진다. 굳이 벡터곱을 쓰지 않고 좀 더 단순한 방법으로도 원점과, p, q가 같은 직선 위에 놓이는지 확인할 수 있다.

코드

"""Solution code for "BOJ 28067. 기하가 너무 좋아".

- Problem link: https://www.acmicpc.net/problem/28067
- Solution link: http://www.teferi.net/ps/problems/boj/28067

Tags: [brute force]
"""

import math
import itertools


def main():
    N, M = [int(x) for x in input().split()]

    all_points = itertools.product(range(N + 1), range(M + 1))
    triangles = {
        frozenset([math.dist(p, q), math.hypot(*p), math.hypot(*q)])
        for p, q in itertools.combinations(all_points, 2)
        if p[0] * q[1] != p[1] * q[0]
    }

    print(len(triangles))


if __name__ == '__main__':
    main()

토론

댓글을 입력하세요:
H R​ C C W
 
ps/problems/boj/28067.txt · 마지막으로 수정됨: 2023/05/27 16:30 저자 teferi