Algorithm/Baekjoon

[99클럽 코테 스터디 1일차][백준 11561]징검다리 (파이썬 풀이)

도깨비젤리 2024. 10. 29. 14:11

🤔 문제 설명 및 입출력


 

 

 

 

 접근 방법


 

최대한 많은 스탭을 밟으려면 무조건 전에 뛰었던 스탭보다 딱 1만큼 많이 가야한다는 아이디어에는 도달했다.

그래서 음 N-1, N-2 .... 1 까지 모두 더하고, 이 값이 N과 같으면 정답으로 하고, N보다 크면 시작점을 1 줄여서 진행해야지~ 라고 생각했는데... 사고를 전개하다보니 뭔가 비효율적이라는 느낌이 들었다. 그리고 이런 일일히 노가다식 덧셈이 딱 N과 맞을꺼라는 보장이 들지 않았다.

 

좀 더 생각해보니까, 결국 전 스탭보다 1 스탭만큼 더 가는 행마를 어떻게든 우겨넣으면 최대 징검다리 밟은 개수가 된다는 사실을 찾아냈고, 이를 노가다로 다시 찾으려다가? 이분 탐색을 이용해서 찾기로 했다 (NOTE: 정렬된 리스트 내에서 특정 값을 search할때는 이분 탐색부터 생각해봐라 ) 

 

 

1부터 시작해서 N에 도착하는데, 전 스탭보다 딱 1만큼 더 가는 것은 등차수열의 합으로 구할 수 있으니, 이분탐색의 매 mid를 등차수열의 합으로 두고, 이 값이 돌의 전체 개수보다 큰 지 작은 지를 비교해서 탐색 범위를 줄이면 된다. 

 

만약 탐색범위 초과 (left > right) 인 경우, right를 초과해서 넘어가면 정답 조건을 만족할 수 없으니, 최대로 갈수 있는 돌은 right까지인걸로 간 주하고, right에서 N번째 돌까지 한번 폴짝 뛰는 것으로 처리한다.

👨‍💻 소스 코드


  • 파이썬
# 11561
# 문제 링크  : https://www.acmicpc.net/problem/11561
import os
import json


def is_local_environment(config_file='local-config.json'):
    if os.path.exists(config_file):
        with open(config_file, 'r') as file:
            config = json.load(file)
            return config.get('local') == bool('true')
    return False

def read_local_file(file_name:str)->None:
    f = open(file_name)
    if f == False:
        return None
    T = f.readlines()
    f.close()
    T = [int(line.strip()) for line in T]
    return T


# 조건
# N번 징검다리는 반드시 밟아야 한다.
# 첫번째 징검다리는 아무것이나 밟을수 있다
# 두번째 점프부터는 이전에 밟은 징검다리의 번호보다 커야한다
# 1 <= number_of_stone <= 10**16
# 밟을 수 있는 최대 징검다리의 수는?

# 최대로 많은 징검다리를 밟으려면 1,2,3,...N-1,N 순으로 계속 1씩 커지면서 밟기
# 1씩 커지는 순서쌍을 어떻게든 우겨넣어야한다. (시작 다리만 바꾸는 방식으)

# 이분 탐색으로 찾기..
def binary_search(left: int, right: int, total_stone: int) -> int:
    if left > right:
        return right
    mid = (left + right) // 2
    sum_of_stone = mid * (mid + 1) // 2
    if sum_of_stone == total_stone:
        return mid
    elif sum_of_stone > total_stone:
        return binary_search(left, mid - 1, total_stone)
    else:
        return binary_search(mid + 1, right, total_stone)


def solution(number_of_stone:int)->int:
    result = binary_search(1, number_of_stone,  number_of_stone)
    return result




def main():
    # local환경 실행
    if is_local_environment():
        local_data = read_local_file('11561.txt')
        number_of_stone = local_data[0]
        for i in range(1,number_of_stone+1):
            print(solution(local_data[i]))
    # BOE환경 실행
    else:
        number_of_stone = int(input())
        for i in range(number_of_stone):
            print(solution(int(input())))


main()

 

 

🔥 강평


 

이분 탐색을 떠올리기가 아직 어렵다. 처음에 문제를 접할때 어떻게 쪼개서 살펴봐야할지를 잘 생각해봐야한다고 생각이 든다

그와 별도로 백준 서버에서 실행되는 코드와 내 로컬에서 실행되는 코드를 구분해서 작성해봤다. 매번 검증할 때마다 노가다로 타이핑하고, 백준에 올릴때는 또 코드를 수정해야했던게 매우매우 귀찮았는데, 이제 그런 귀찮은 일 아예 없겠다. 우하하