BOJ 13957 Within Arm's Reach

BOJ 13957 Within Arm's Reach

문제 링크:

문제 내용

nn개의 선분으로 이루어진 로봇 팔이 있습니다. 이 로봇 팔의 시작점은 원점에 고정되어 있으며, 첫 번째 선분의 각도와 각 관절의 각도는 자유롭게 바꿀 수 있고, 여러 선분이 서로 겹쳐도 됩니다.

로봇 팔의 끝점이 목표 지점 (x,y)(x, y)에 가장 가깝게 위치하도록 하는 방법을 아무거나 하나 찾으세요.

입력

첫 줄에는 nn의 값이 주어집니다. (1n201 \le n \le 20) 다음 nn줄에는 각 선분의 길이 lil_i가 순서대로 주어집니다. (1li10001 \le l_i \le 1000)

그다음 줄에는 목표 지점의 좌표 (x,y)(x, y)가 주어집니다. (20  000x,y20  000-20\;000 \le x, y \le 20\;000) 모든 입력은 정수입니다.

출력

nn줄을 출력합니다. 첫 번째 줄에는 첫 번째 선분의 원점의 반대쪽 끝점의 좌표를, 그 다음부터 ii번째 줄에는 ii번째 선분의 끝점의 좌표를 출력합니다.

원점에서 첫 번째 좌표까지의 거리는 l1l_1과 절대 오차 0.010.01 이내에 있어야 하며, 마찬가지로 i1i-1번째에서 ii번째 좌표까지의 거리는 lil_i와 절대 오차 0.010.01 이내에 있어야 합니다. 또한, 마지막 출력된 좌표에서 목표 지점까지의 거리도 정답의 거리와 절대 오차 0.010.01 이내여야 합니다.

문제 풀이

스포일러

먼저, 최종적으로 닿는 좌표는 nn개의 선분이 만드는 nn개의 벡터의 합이므로, 길이들을 적절히 재배열해서 각각의 벡터를 구한 다음 원래의 순서로 재배열하여 누적 벡터 합을 출력하면 됩니다.

엣지 케이스는 다음과 같은 경우가 있습니다.

  • 모든 lil_i의 합보다 목적지가 멀리 있는 경우, 모든 벡터를 목적지 방향으로 뻗는 것이 최적입니다.
  • 모든 lil_i 중에서 가장 긴 것을 lmaxl_{max}라고 하고, 그 외의 lil_i들의 합을 lrestl_{rest}라고 합시다. 이때 lmax>lrestl_{max} > l_{rest}이면, 원점에서 lmaxlrestl_{max} - l_{rest} 보다 가까운 점에는 닿을 수 없습니다. 이때는 lmaxl_{max}를 목적지 방향으로 뻗고 나머지를 원점으로 돌아오는 방향으로 설정하는 것이 최적입니다.

그 외의 모든 경우에는 목적지에 정확히 닿을 수 있습니다. 원점에서 목적지까지의 거리를 dd라고 합시다.

  • lmax>lrestl_{max} > l_{rest}이면서 닿을 수 있는 경우는 거리가 lmaxlrestl_{max} - l_{rest} 이상, lmax+lrestl_{max} + l_{rest} 이하입니다. 이때는 (d,lmax,lrest)(d, l_{max}, l_{rest})가 삼각형을 이룰 수 있습니다. (degenerate 삼각형 포함) 삼각형의 세 변의 길이가 주어질 때 내각은 코사인 제2법칙을 이용하여 구할 수 있습니다. 이는 degenerate 삼각형에서도 통하지만 실수 오차로 인해 NaN이 나올 수 있으므로, 변의 길이를 0.0010.001 정도 조절하여 확실하게 삼각형이 되도록 하여 구하는 것이 좋습니다.
  • lmaxlrestl_{max} \le l_{rest}인 경우는 d>lmaxd > l_{max}인 경우와 아닌 경우로 나눕니다.
    • d>lmaxd > l_{max}라면, lmaxl_{max}를 포함한 모든 변들을 적절히 두 개의 집합으로 나눠서 두 길이의 합의 차이가 lmaxl_{max} 이하가 되게 만들 수 있습니다. n20n \le 20이므로 적당한 분할을 브루트포스로 구해 줍니다. 그러면 dd와 두 개의 합은 삼각형을 이룹니다.
    • dlmaxd \le l_{max}라면, 먼저 lmaxl_{max} 하나를 이용하여 (x,y)(x, y)에서 정확히 lmaxl_{max}만큼 떨어진 점으로 이동합니다. 그 뒤에 lrestl_{rest}를 마찬가지로 차이 lmaxl_{max} 이하인 두 집합으로 분할하여 목적지로 이동합니다.
Last updated on