본문 바로가기

알고리즘/백준 문제 풀이

[Python] 32773번 회전 관성 모멘트

728x90

 

 

https://www.acmicpc.net/problem/32773


 

24/11/26

 

 

오랜만에 일반 물리학의 내용을 한 번 복습할 수 있게 했던 문제다.


 

문제 접근 방식:

 

 

문제의 목표는 $xy$평면 위에 정의된 다각형 판이 있을 때, 이 다각형 판을 $z$축에 대해서 회전시킬 때의 회전 관성 모멘트를 구하는 것이다.

 

이때의 회전 관성 모멘트는 다음과 같이 정의된다.

 

$$\int r^{2} \, dm$$

 

이때 $r$은 회전 축으로부터의 거리를 나타내며, $dm$은 그 질점의 미소 질량을 뜻한다.

 

$x$좌표와 $y$좌표가 주어지므로, 거리를 다음과 같이 찢어서 표현할 수 있다.

 

$$\int x^{2} \, dm + \int y^{2} \, dm$$

 

근데 이건 $x$축으로 다각형 판을 돌릴 때의 회전 관성 모멘트, $y$축으로 다각형 판을 돌릴 때의 회전 관성 모멘트이다.

 

편의 상 회전 관성 모멘트를 $I$로 표기하면, $I_{z} = I_{x} + I_{y}$가 성립한다.

 

그리고 이를 수직 축 정리(Perpendicular axis theorem)라고 부른다.

 

그래서 문제는 $I_{x}$랑 $I_{y}$를 어떻게 구하냐로 연결된다.

 

다각형의 점들이 $P_{0}, P_{1}, \dots, P_{n-1}$로 주어져 있다고 하고, 점 $P_{i}$의 좌표가 $(x_i, y_i)$라고 하자. 또한 다각형의 영역을 $R$이라고 하자.

 

다각형 판의 밀도가 $1$이기 때문에, 미소 질량에 대해서 적분하는 것은 미소 면적에 대해 적분하는 것과 동일하다.

 

따라서, 다음과 같이 $I_{x}$를 다시 적을 수 있다.

 

$$I_{x} = \iint_{R} y^{2} \, dx \, dy$$

 

더더욱 어떻게 구할 지 감이 안올 수도 있다. 이제, 다각형 판들을 $n$개의 삼각형 판들로 분할하고, 이 삼각형 판들에 대한 $I_{x}$들을 모두 더하는 것으로 생각해보자.

 

각 삼각형은 $z$축을 기준으로 분할되므로, 삼각형 $T_{i}$의 좌표는 $(0, 0), (x_{i}, y_{i}), (x_{i+1}, y_{i+1})$로 적을 수 잇다.

 

이제 면적분을 하면 된다.

 

면적분을 하기가 힘들다면, 그린 정리를 사용해도 된다.

 

그린 정리는 선적분과 면적분 사이의 관계를 알려주는 정리로, 다음과 같이 정리된다.

 

$$\iint_{R} \left( \frac{\partial Q}{\partial x} - \frac{\partial P}{\partial y} \right) = \oint_{\partial R} (P dx + Q dy)$$

 

왼쪽에서 $P = 0, Q = xy^{2}$으로 잡고, 각 삼각형 선분에 대해서 선적분하면 된다.

 

각 삼각형의 선분은 직선이기 때문에 $x$항을 $y$로 표현할 수 있다.

 

정리하면 다음과 같이 나온다.

 

$$I_{x} = \frac{1}{12} \sum_{i=0}^{n-1} (x_{i}y_{i+1} - x_{i+1}y_{i}) (y_{i}^{2} + y_{i}y_{i+1} + y_{i+1}^{2})$$

 

비슷하게 $I_{y}$도 정리할 수 있고, 두개를 더하면 된다.


아래는 내가 위의 접근 방식과 같이 작성한 파이썬 코드이다. 더보기를 누르면 확인할 수 있다.

더보기
# 32773번 회전 관성 모멘트
# 물리학, 미적분학
'''
접근 방법:
수직 축 정리 이용
'''
import sys
input = sys.stdin.readline

N = int(input())
x, y = [], []
for _ in range(N):
    xi, yi = map(float, input().split())
    x.append(xi)
    y.append(yi)
J_x, J_y = 0, 0
for i in range(N):
    p = (x[i]*y[(i+1)%N] - x[(i+1)%N]*y[i])
    q_x = (y[i]**2 + y[i]*y[(i+1)%N] + y[(i+1)%N]**2)
    q_y = (x[i]**2 + x[i]*x[(i+1)%N] + x[(i+1)%N]**2)
    J_x += p*q_x
    J_y += p*q_y
J_z = (J_x + J_y)/12
print(f'{round(abs(J_z), 1):.1f}')