사용한 알고리즘
알고리즘 설명
- 줄자를 실제로 접는 듣이 진행하면 된다.
- 줄자의 중점과 두점을 접었을 때에 좌표가 어떻게 바뀌는지 정의한다.
- 줄자의 중점을 mid_L 이라고 하고, 접혀저야 하는 부분을 mid라고 할때, mid_L < mid 인 경우 줄자는 오른쪽에서 왼쪽으로 접히며, mid_L > mid 인 경우 줄자는 왼쪽에서 오른쪽으로 접힌다.
- 이를 이용하면 두가지 경우로 나누어 볼 수 있다.
- Case1. 오른쪽에서 왼쪽으로 접히는 경우
- 접히는 부분의 오른쪽인 경우
(mid < 좌표 x), (mid,x) -> (mid, mid-(x-mid))
- 접히는 부분의 왼쪽인 경우 좌표가 옮겨지지 않는다.
(좌표 x <= mid), (x,mid) -> (x, mid)
- Case2. 왼쪽에서 오른쪽으로 접히는 경우
- 접히는 부분의 오른쪽인 경우
(mid < 좌표 x), (mid,x) -> (0, x-mid)
- 접히는 부분의 왼쪽인 경우
(좌표 x < mid), (x, mid) -> (mid-x, 0)
- 위 두 알고리즘을 이용하여 3번 접으면 된다.
- 접은 뒤에 남겨진 줄자는 max(mid, N-mid) 둘 중 하나이다.
값이 mid 인 경우는 Case1, N-mid인 경우는 Case2이다.
풀이
// baekjoon 2597 yechan
#include <cstdio>
#include <algorithm>
using namespace std;
typedef pair<float,float> P;
float N;
P points[3];
int main() {
scanf("%f", &N);
for (int i=0; i<3; i++) {
scanf("%f%f", &points[i].first, &points[i].second);
// 저장 첫번째 요소가 항상 작은 요소로 유지
if (points[i].first > points[i].second)
swap(points[i].first, points[i].second);
}
// 3번 접기 (빨 -> 파 -> 노)
for (int i=0; i<3; i++) {
// 이미 같은 위치에 있는 경우
if (points[i].first == points[i].second) continue;
// 두 점의 중간 지점 찾음
float mid = (float)(points[i].second + points[i].first)/2.f;
// 줄자의 중간보다 오른쪽에 있는 경우 (접으면 줄자의 오른쪽이 남겨짐)
if (mid < N-mid) { // right
for (int j=i+1; j<3; j++) {
// 접혀져서 (x, mid) -> (mid-x, 0)형태로 바뀜
if (points[j].first < mid) points[j].first = mid - points[j].first;
// 이미 오른쪽에 있어서 (mid, x) -> (0, x-mid)
else points[j].first -= mid;
// 위와 같은 알고리즘
// (y, mid) -> (mid-y, 0)
if (points[j].second < mid) points[j].second = mid - points[j].second;
// (mid, y) -> (0, y-mid)
else points[j].second -= mid;
// 접은 뒤에도 첫번째 좌표 < 두번째 좌표 를 유지시킴
if (points[j].first > points[j].second)
swap(points[j].first, points[j].second);
}
N = N-mid;
// 줄자의 중간보다 왼쪽에 있는 경우 (접으면 줄자의 왼쪽이 남겨짐)
} else { // left
for (int j=i+1; j<3; j++) {
// (mid, x) -> (mid, mid-(x-mid))
if (mid < points[j].first) points[j].first = mid - (points[j].first - mid);
if (mid < points[j].second) points[j].second = mid - (points[j].second - mid);
// 나머지 경우 (x, mid) -> (x, mid)로 유지되어 아무것도 하지 않아도 됨
// 접은 뒤에도 첫번째 좌표 < 두번째 좌표를 유지시킴
if (points[j].first > points[j].second)
swap(points[j].first, points[j].second);
}
N = mid;
}
}
printf("%.1f\n", N);
return 0;
}