좌표들이 주어질때 좌표간 간격이 될 수 있는 모든 수를 찾는 방법
30105번: 아즈버의 이빨 자국 (acmicpc.net)
초코바에 이빨 자국을 남기는데 이빨간 간격이 k라고 한다면 0이상의 수 x에 대하여 x부터 x+k에 이빨 자국을 남긴다
이빨자국을 동일한 위치에 여러번 남겨도 한번만 보인다
이빨자국이 남겨진 좌표들 x0,x1,x2,...,xn이 주어진다면 가능한 k를 모두 구해본다면?
1. 무식하게 찾는 방법
쉽게 생각할 수 있는 방법은.. 일단 모든 좌표쌍 (xi,xj)에 대하여 간격 k = xj - xi를 구하고
간격 k에 대응하는 xi,xj를 저장해둔다
모든 간격 k에 대하여 간격 k에 대응하는 x좌표가 주어진 이빨 자국 수와 같다면 해당 간격 k는 가능한 k라는 것
예를 들어 [0,5,10,15]로 주어질때
모든 쌍에 대하여 5-0 = 5이므로 h[5] = [0,5], 10-0 = 10이므로 h[10] = [0,10],...
10-5 = 5이므로 h[5] = [0,5,10], ... 15-10 = 5이므로 h[5] = [0,5,10,15]이므로...
k = 5는 가능한 k이다.
마찬가지로 15 - 5 = 10이므로 h[10] = [0,10,5,15]이므로 역시 k = 10도 가능한 k이다.
하지만 15 - 0 = 15에서 h[15] = [0,15]만 존재하므로 k = 15는 불가능한 k이다.
n = int(input())
A = list(map(int,input().split()))
h = {}
for i in range(n-1):
for j in range(i+1,n):
k = A[j] - A[i]
if h.get(k,0) == 0:
h[k] = set()
h[k].add(i)
h[k].add(j)
answer = []
for k in h:
if len(h[k]) == n:
answer.append(k)
answer.sort()
print(len(answer))
print(*answer)
2. 조금 더 똑똑하게 찾는 방법
브루트포스의 백미는 탐색 범위를 줄이는데 있다
위에서 가능한 간격 k를 모든 (xi,xj)에 대해 조사했지만 (x0,xi)에 대해서만 조사한다면...
k = xi - x0에 대하여 0번과 i번을 물었으니 j = 1번부터 조사해서 xj, xj+k = xj, xj+(xi-x0)에도 물 수 있는지 조사하면 된다
즉 X값들을 미리 hash에 저장해두고 i = 0,1,2,...에 대하여 k = xi - x0로 해두고
j = 1,2,...에 대하여 xj + (xi-x0) = xj + k가 hash에 존재하는지만 확인하면 충분하다
#x0,x1,..,xn이 주어지고 k > 0 , xi,xi+k에 좌표를 남겼을때 가능한 k를 모두 찾는 방법
n = int(input())
A = list(map(int,input().split()))
#X값들을 미리 저장해두고
h = {}
for i in range(n):
h[A[i]] = 1
answer = []
#i = 1,2,..,n-1에 대해 k = xi - x0에 대하여 x0,xi에 좌표를 남겼다면
#j = 1,2,..,n-1에 대해 xj,xj+k에 좌표를 모두 남길 수 있다면 충분하다
for i in range(1,n):
k = A[i] - A[0]
no = False
for j in range(1,n):
#[xj,xj+k]가 존재하면 상관없긴한데, 존재하지 않는다면
if h.get(A[j] + k,0) == 0:
#[xj-k,xj]가 존재한다면 조건을 만족하게 된다
#이걸 확인하지 않으면
#[0,5,10,15]의 경우 k = 5에서 [0,5], [5,10], [10,15]까지 보다가
#[15,20]이 존재하지 않으니 k = 5는 불가능하다!라고 결론내린다
#[10,15]가 존재하니 k = 5가 가능하다라고 할려면 xj-k를 봐야함
if h.get(A[j] - k,0) == 0:
no = True
break
if no == False:
answer.append(k)
print(len(answer))
print(*answer)
여기서 주의할 점은 xj에 대하여 xj+k가 존재하는지 확인하면 된다고 했지만
xj+k가 존재하지 않더라도 xj-k가 존재한다면 xj-k, xj로 조건을 만족하기 때문에 상관없다
예를 들어 [0,5,10,15]일때 k = 5-0에 대하여 [0,5], [5,10],[10,15]까지는 무리없이 가다가
xj = 15일때 xj+k = 20이 존재하지 않으니까 조건을 만족하지 않는다? 하면 안되잖아
xj = 15일때 xj-k = 10이 존재하여서 [10,15]가 존재하니까 조건을 만족하게 된다
'알고리즘 > 브루트포스' 카테고리의 다른 글
탐색 범위를 줄여야하는 브루트포스 연습2 - 컴퓨터로 종이접기? (0) | 2024.10.25 |
---|---|
탐색 범위를 줄여야하는 브루트포스 연습1 - 각 자릿수의 제곱합? (0) | 2024.10.24 |
그래프에서 서로 연결된 세 정점의 차수 합의 최솟값 찾기 (0) | 2024.09.10 |
모든 집합의 합집합과 다르게 되는 일부를 골라 만든 최대 합집합 (0) | 2024.09.09 |
생각해서 브루트포스 탐색 범위를 줄여야하는 경우1 (장난감 강아지) (0) | 2024.02.03 |