[백준] 17371 - 이사

2021. 3. 30. 20:19·알고리즘 (PS)/BOJ
반응형

www.acmicpc.net/problem/17371

 

17371번: 이사

$(\frac{2}{3}, \frac{1}{3})$으로 이사를 가면 가장 가까운 편의시설은 (0, 1)으로 거리는 $\frac{2\sqrt{2}}{3}$이고, 가장 먼 편의시설은 (-4, 1) 혹은 (4, -3)으로 거리는 둘 다 $\frac{10\sqrt{2}}{3}$이다. 두 거리의

www.acmicpc.net

 

그리디 알고리즘 연습문제로 풀게된 '이사' 문제이다.

고민끝에 다른 분의 풀이를 봤다.

 

burningjeong.tistory.com/293

 

17371 이사

이런 문제가 기하인가? 원 공식이랑 비슷하니 원을 사용하나? 고민 많이 했는데 그리디 문제였다. 길이의 평균을 구하는 거라 집이 편의점 위에 가도 값의 차이는 없다. 그래서 편의점 사이의 거

burningjeong.tistory.com

그런데 미천한 내 이해력으론 이 분의 풀이 설명을 봐도 이해가 안됐다.

그래서 이 분의 소스코드를 읽고 문제를 보고 교차비교해가며 이해했다.

 

이 문제의 핵심은 다음 부분이다.

 

"그나마 좌표를 찾기 쉽도록

가장 가까운 편의시설까지의 거리와 가장 먼 편의시설까지의 거리의 평균이

최소가 되는 좌표로 이사하려고 한다."

 

결론적으론 이 말을 그대로 구현해서 이 문제를 풀 수 있다.

N=1000 이기 때문에, 1000개의 점들 간의 거리를 나이브하게 모두 구해도

1,000 * 1,000 = 1,000,000 이기 때문에 모든 거리를 다 체크할 수 있다.

가장 가까운 편의시설부터 가장 먼 편의시설까지의 거리 평균을 다 구해서 그 중에 최소를 찾으면 된다.

하지만 편의시설간 거리와 집의 좌표가 어떤 관계가 있는지는 바로 이해하기 힘들다.

그 관계성을 찾아보자.

 

이 문제의 답으로 출력해야 하는 것은 '가장 짧은 거리가 되는 좌표' 이다.

그런데 사실 좌표값 자체는 중요하지 않다.

 

문제의 출력란을 보자.

 

첫 번째 줄에 혜아가 이사할 곳의 좌표 (Hx, Hy)를 나타내는

두 실수 Hx, Hy를 공백 하나로 구분하여 출력한다.

가장 가까운 편의시설까지의 거리와 가장 먼 편의시설까지의 거리의 평균을

정답과 비교했을 때 절대오차 혹은 상대오차가 10-6 이하면 정답으로 인정한다.

 

출력해야하는 값이 좌표이다보니

나도 모르게 좌표를 구하려고 고민하던 과정에서 막혔던 점이 컸다.

 

좌표는 여러개가 될 것 같은데 어떻게 구해야하지? 식을 세워서 계산해야하나?

이런 생각에 빠져서 헤어나오질 못했다.

 

일정 오차이하 + 예제 출력 좌표에 6자리 소수점 표기까지, 문제를 대충 읽으면 당하기 쉬운 것 같다

하지만 사실 이 문제에서 요구하는 것은 좌표가 아닌 거리이다.

 

출력한 좌표로부터 가장 가까운 편의점과 가장 먼 편의점 사이의

거리 평균값이 원래 정답과 일정 오차이하이면 되는 것이다.

그렇다면 어차피 거리의 평균값의 최소를 구해야하는 것이고,

 

평균값이라 함은

(가장 가까운 거리 + 가장 먼 거리) / 2 인데

사실 거리를 출력하는 것이 아니기 때문에, / 2는 계산할 필요도 없이

(가장 가까운 거리 + 가장 먼 거리) 가 최소가 되는 좌표를 아무거나 출력하면 된다.

 

이제 여기에서 생각을 단순하게 해볼 수 있다.

문제 조건에서

 

이 좌표계에는 그 어떤 위치에도 주거할 수 있는 시설이 있기 때문에

혜아는 두 실수 Hx, Hy 를 골라 좌표 (Hx, Hy)로 이사할 것이다.

 

라고 했다.

그렇다면 편의시설 위에 집이 있어도 상관이 없다.

그럼 가장 가까운 거리는 이제 생각할 필요가 없어졌다.

편의시설 위치를 집의 위치라고 하면 가장 가까운 거리는 0이기 때문이다.

 

그럼 한 편의시설을 골라 그 편의시설 위치에 집이 있다고 가정하고

그 편의시설의 위치로부터 가장 먼 편의시설의 값을 구하면

문제에서 요구하는 (집에서 가장 가까운 편의시설까지 거리 + 가장 먼 편의시설까지 거리) 를 한번에 구할 수 있다.

 

( 0 + 집으로부터 가장 먼 편의 시설까지 거리 )

= (내가 선택한 편의시설로부터 가장 먼 편의시설까지의 거리)

 

편의 시설은 N개가 있으니, 총 N개의 값을 구할 수 있을 것이다.

그리고 이 값들 중 가장 작은 값을 찾으면 된다.

그럼 집의 좌표는 어떻게 될까?

"가장 작은 값을 갖게 만든 가장 가까운 편의시설의 위치"

= "거리를 구할 때의 기준 위치"를 출력하면 된다.

집으로부터 가장 가까운 편의시설까지 거리를 0으로 가정했기 때문이다.

 

파이썬으로 내가 제출한 코드는 다음과 같지만,

위에 소개한 분의 코드로 그 분의 아이디어를 이해하고나니

사실상 그 분의 코드를 파이썬으로 옮긴 것에 지나지 않게 되었다.

# 17371 이사
import sys

def distance(x1, y1, x2, y2):
    return (x2-x1)**2 + (y2-y1)**2
    
n = int(input())
convini = []

for _ in range(n):
    convini.append(tuple(map(int, sys.stdin.readline().split())))

_min = 9876543210
_min_idx = -1

for i in range(n):
    _max = -1
    _m_idx = -1
    for j in range(n):
        d = distance(convini[i][0], convini[i][1], convini[j][0], convini[j][1])
        if _max < d:
            _max = d
            _m_idx = i
    if _max < _min:
        _min = _max
        _min_idx = _m_idx
        
print(convini[_min_idx][0], convini[_min_idx][1])

 

문제를 풀다가 문득, 그냥 모든 편의시설 사이의 거리를 모두 구해서

그 중 가장 짧은 값을 구하면 더 효율적이지 않을까? 하는 생각도 했었다.

 

어차피 다 정리하면 O(n^2)의 시간복잡도 인 건 똑같지만,,

n^2으로 다 구하는 것보다 nC2의 조합으로 구하는게 더 효율적이라고 생각했다.

 

하지만 nC2로 구하게 되면 문제가 발생한다.

어느 점이 기준점인지 알 수가 없는 점이다.

이 문제에서는 (n, k) 를 n번째 편의시설부터 k번째 편의시설까지 거리라고 했을 때

(n, k)와 (k, n)이 갖는 값은 같을지 몰라도, 이 둘이 의미하는 것은 전혀 다르다.

 

(n, k) 는 n번째 편의시설에 집이 있다고 가정할 때의 거리이고

(k, n) 은 k번째 편의시설에 집이 있다고 가정할 때의 거리이다.

이 둘을 같은 것으로 취급하면 어떤 편의시설에 집이 있었는지를 알 수 없게된다.

따라서 단순하게 조합만 사용해서는 답을 찾을 수 없다.

(미리 기억해놨다가 갖다 쓰는 건 가능하겠지만,

오히려 공간복잡도 낭비에, 코드만 더 복잡해질 것 같다고 생각한다.)

 

burningjeong.tistory.com/293

 

17371 이사

이런 문제가 기하인가? 원 공식이랑 비슷하니 원을 사용하나? 고민 많이 했는데 그리디 문제였다. 길이의 평균을 구하는 거라 집이 편의점 위에 가도 값의 차이는 없다. 그래서 편의점 사이의 거

burningjeong.tistory.com

마지막으로 위에 소개한 분의 링크를 다시 달면서 문제 정리를 마친다.

반응형
저작자표시 비영리 변경금지 (새창열림)

'알고리즘 (PS) > BOJ' 카테고리의 다른 글

[백준] 5719 - 거의 최단 경로  (0) 2021.04.17
[백준] 2662 - 기업 투자  (0) 2021.04.06
[백준][C++] 9935 문자열폭발  (0) 2021.02.13
[백준][C++] 19541 루머  (0) 2021.02.08
[백준][Python3] 20500 - Ezreal 여눈부터 가네 ㅈㅈ  (0) 2021.01.24
'알고리즘 (PS)/BOJ' 카테고리의 다른 글
  • [백준] 5719 - 거의 최단 경로
  • [백준] 2662 - 기업 투자
  • [백준][C++] 9935 문자열폭발
  • [백준][C++] 19541 루머
에버듀
에버듀
개발은 좋은데 뭘로 개발할까
  • 에버듀
    Blog. 에버듀
    에버듀
  • 전체
    오늘
    어제
    • 분류 전체보기 (614)
      • 개인 프로젝트 (43)
        • 토이 프로젝트 (3)
        • [2020] 카카오톡 봇 (9)
        • [2021] 코드악보 공유APP (22)
        • [2022] 유튜브 뮤직 클론코딩 (9)
        • [2025] 한글 SQL 데이터베이스 (0)
      • 팀 프로젝트 (22)
        • [2020] 인공지능 숫자야구 (4)
        • [2022] OSAM 온라인 해커톤 (10)
        • [2024] GDSC 프로젝트 트랙 (6)
        • [2025] 큰소리 웹 페이지 (2)
      • CS (335)
        • 자료구조 (19)
        • 어셈블리 (41)
        • 멀티미디어응용수학 (7)
        • 컴퓨터 구조 (29)
        • 알고리즘 분석 (4)
        • 컴퓨터 네트워크 (38)
        • 프로그래밍언어론 (15)
        • HCI 윈도우즈프로그래밍 (26)
        • 기초데이터베이스 (29)
        • 운영체제 (23)
        • 오토마타 (24)
        • 문제해결기법 (11)
        • 블록체인 (22)
        • 소프트웨어공학 (21)
        • 기계학습심화 (12)
        • 컴퓨터그래픽스와 메타버스 (8)
        • 분산시스템특론 (6)
      • 자기계발 (44)
        • 생각 정리 (22)
        • 대외활동 (11)
        • 동아리 (7)
        • 자격증 (3)
        • 머니 스터디 (1)
      • 알고리즘 (PS) (107)
        • BOJ (101)
        • Programmers (5)
        • 알고리즘 이모저모 (1)
      • WEB(BE) (8)
        • express.js (1)
        • Spring & Spring Boot (7)
      • WEB(FE) (2)
        • html, css, js (1)
        • React.js (1)
      • Tool & Language (6)
        • Edit Plus (1)
        • Git (1)
        • Python3 (2)
        • Java (2)
      • Infra (12)
        • AWS (1)
        • Oracle Cloud (8)
        • Firebase (2)
        • Network (1)
      • Android (18)
        • Java (6)
        • Flutter (12)
      • Window (2)
        • Visual Studio 없이 WPF (1)
        • MFC (1)
      • 독서 (14)
        • Inside Javascript (7)
        • Database Internals (6)
        • 한 글 후기 (1)
  • 링크

    • github
    • website
  • 인기 글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.6
에버듀
[백준] 17371 - 이사
상단으로

티스토리툴바