N개의 샘터가 주어질때 K채의 집을 지을려고 한다
각 집에서 가장 가까운 샘터까지의 거리를 불행도라고 정의할때 K채의 집의 모든 불행도의 합이 최소가 되도록 집을 짓는다
그 불행도의 합의 최소를 구하는 문제
-------------------------------------------------------------------------------------------------------------------
BFS로 풀 수 있다는데 생각해봐도 감이 잘 안오더라고... 평소 BFS문제랑 조금 달라서 그런지
샘터 위치 x에서 왼쪽 오른쪽으로 -1,1만큼 봐서 비어있으면 x-1, x+1에 집을 짓고
다시 x-1에서 왼쪽 오른쪽으로 -1,1만큼 x-1,x에서 비어있으면 집을 짓고
x+1에서 왼쪽 오른쪽으로 -1,1만큼 x,x+1에서 비어있으면 집을 짓고
....
이를 반복하면 될것 같다
처음에 샘터 위치 x를 모두 큐에 넣은 다음 큐에서 위치 하나씩을 빼서 왼쪽 오른쪽 -1,1만큼만 봐서
비어있으면 집을 지은 다음 그 위치를 큐에 다시 넣어준다
집을 짓는데 성공했다면 카운팅을 해주고 샘터에서까지 거리를 누적해준다
총 K채를 짓는데 성공했다면 반복을 멈추면 끝
집을 짓는데 성공했다면 그 집은 확실히 가장 가까운 집중 하나이기 때문에 카운팅을 해주면 됨
그리고 샘터에서까지 거리는 처음에 샘터 위치를 큐에 넣을 때 (x,0)으로 넣어주고
매 행위마다 1씩 증가시켜서 (x,c+1)을 넣어주면 현재 샘터에서까지 거리를 알 수 있을 것
-------------------------------------------------------------------------
근데 그 집을 짓는 위치가 더 가까운 샘터가 있을 수도 있는거 아님?
그랬으면 이미 그 위치는 다른 샘터에 의해 집이 지어져있는 곳일거라 그런 경우는 불가능하다
그리고 visited 체크할 때는 어떻게 해야하지
샘터 위치 범위가 -10^8에서 10^8이다보니 단순히 배열로 만들면 메모리 초과날것
좌표 압축을 시도해볼 수도 있긴한데 어차피 n이 10만이라 굳이 그래야하나
hash나 set으로 저장을 하면 된다 그러면 O(1)에 확인 가능
from collections import deque
n,k = map(int,input().split())
A = list(map(int,input().split()))
visited = {}
queue = deque([])
#(샘터 위치, 샘터까지 거리)를 모두 큐에 넣고
for i in range(n):
visited[A[i]] = 0
queue.append((A[i],0))
count = 0
v = 0
while queue:
x,c = queue.popleft()
#현재 위치에서 왼쪽 -1, 오른쪽 +1 부분을 확인
#비어있으면 집을 짓고 샘터까지 거리 c+1를 누적해줌
#집을 짓는데 성공하면 1씩 counting해서 총 k개 지으면 끝
if visited.get(x-1,-1) == -1:
visited[x-1] = 1
v += c+1
queue.append((x-1,c+1))
count += 1
if count == k:
break
if visited.get(x+1,-1) == -1:
visited[x+1] = 1
v += c+1
queue.append((x+1,c+1))
count += 1
if count == k:
break
print(v)
'알고리즘 > DFS BFS 정복기' 카테고리의 다른 글
flood fill 핵심 트릭 - 사각형으로 둘러쌓인 연결요소의 둘레의 길이(연결요소 내부 영역을 찾는 방법) (0) | 2025.02.16 |
---|---|
해밍거리 + BFS 경로 역추적하기 (0) | 2025.02.03 |
BFS로 어떤 정수의 0과 1로만 이루어진 배수 찾기 (0) | 2025.01.28 |
퍼져나갈 수 있는지를 묻고 있지만 도달할 수 있는지를 계산해야하는 BFS (0) | 2025.01.25 |
트리에서 임의의 노드에서 모든 노드를 적어도 1번 이상 방문하는데 걸리는 최소 거리 (0) | 2024.07.11 |