https://www.acmicpc.net/problem/4105
4105번: 유클리드
유클리드는 자신의 공책에 다음과 같은 문제를 풀기 위한 복잡한 과정을 적어놓았다. 하지만, 컴퓨터를 이용하면 쉽게 구할 수 있다. 이차원 평면 위에 선분 AB와 점 C, 삼각형 DEF가 있다. 점 C는
www.acmicpc.net
기하학 문제를 풀 때 연습장을 쓰게 되더라. 그래도 다른 카테고리의 문제들은 애매한 부분이 남아 문제를 완벽히 풀었다는 생각이 잘 들지 않는데, 이런 문제들은 수식으로 정확히 표현되니까 정말 좋다.
접근
일단 삼각형과 평행사변형의 넓이가 같다는 조건을 쓰기 위해 삼각형의 넓이를 구해야 한다.
세 변만 주어졌으므로 헤론의 공식을 통해 삼각형의 넓이를 구해보았다.
이 넓이가 평행사변형의 넓이과 같다는데, 평행사변형의 넓이를 구하는데에는 두 가지 공식이 있다.
하나는 밑변 * 높이이고, 다른 하나는 두 변 a, b를 이용하는 건데, 이다.
이 문제에서 선분 AB와 직선 AC가 주어졌기 때문에 후자가 적절하다. 전자로 했다가 30분동안 끙끙대고 후자를 떠올렸다.
평행사변형의 넓이를 S라고 한다면,
는 임의의 점 와 점 의 길이인데 아직 모르고, 는 알고 있다. 는 내적 공식을 통해 유도해낼 수 있다.
여기서 얻은 를 평행사변형의 넓이에 대입하면 를 얻을 수 있다.
이제 의 좌표를 구한 다음 에 를 더하면 ,즉 점 도 얻을 수 있다.

는 직선 위에 있다. 점 로부터 x축에 평행한 임의의 직선을 놓고 점 , 점 에서 내린 수선의 발을 라고 할 때 와 는 닮음인 것을 볼 수 있다. 이 말은 라는 것이다.
이 비율에 관한 관계를 에 대해 정리하면,
이렇게 를 구했는데 이건 점 의 x좌표로부터 얼마나 떨어져 있는지를 나타낸다. 그러므로 점 의 x좌표값을 더해주면 H의 x좌표를 얻을 수 있다.
동일하게 점 로부터 y축에 평행한 임의의 직선을 놓고 점 , 점 에서 내린 수선의 발을 라고 한 후 직전의 공식을 적용하면 H의 좌표는 다음과 같다.
점 의 좌표도 곧바로 구해진다.
미흡했던 점
평행사변형 넓이를 구하는 공식이 여러가지가 있었는데 각도를 쓰는 공식을 떠올리지 못했다.
1시간 반 정도 걸려서 풀었는데 공식을 완벽하게 정리하지 못한 상태로 허겁지겁 답을 제출하려 했었다. 특히 마지막 H의 좌표를 구할 때 벡터 덧셈을 헷갈려했었다.
#include <cmath>
#include <iostream>
#define ABS(X) ((X) > 0 ? (X) : -(X))
struct Point {
double x, y;
};
double d(Point p1, Point p2) {
return sqrt((p1.x - p2.x) * (p1.x - p2.x) + (p1.y - p2.y) * (p1.y - p2.y));
}
bool isZero(Point p1) { return p1.x == 0 && p1.y == 0; }
int main() {
Point A, B, C, D, E, F;
while (1) {
scanf("%lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf", &A.x, &A.y, &B.x,
&B.y, &C.x, &C.y, &D.x, &D.y, &E.x, &E.y, &F.x, &F.y);
if (isZero(A) && isZero(B) && isZero(C) && isZero(D) && isZero(E) &&
isZero(F)) {
return 0;
}
double DE = d(D, E), EF = d(E, F), FD = d(F, D), s = (DE + EF + FD) / 2,
DEF = sqrt(s * (s - DE) * (s - EF) * (s - FD));
Point ABvec = {B.x - A.x, B.y - A.y}, ACvec = {C.x - A.x, C.y - A.y};
double cosTheta =
ABS(ABvec.x * ACvec.x + ABvec.y * ACvec.y) / (d(A, B) * d(A, C)),
sinTheta = sqrt(1.0 - pow(cosTheta, 2)),
AH = DEF / (d(A, B) * sinTheta);
Point H = {A.x + (C.x - A.x) * (AH / d(A, C)),
A.y + (C.y - A.y) * (AH / d(A, C))},
G = {H.x + B.x - A.x, H.y + B.y - A.y};
printf("%.3lf %.3lf %.3lf %.3lf\n", G.x, G.y, H.x, H.y);
}
}
모든 입력이 0일 경우를 처리하기 위해 함수를 사용했다.
'프로그래밍 > 알고리즘' 카테고리의 다른 글
2502 떡 먹는 호랑이 (0) | 2022.09.07 |
---|---|
1876 튕기는 볼링공 (0) | 2022.09.06 |
2527 직사각형 (0) | 2022.09.03 |
18187 평면 분할 (0) | 2022.09.03 |
4811 알약 (0) | 2022.09.02 |
댓글