Skip to content

Conversation

@Mingguriguri
Copy link
Collaborator

주 목표 문제 수: 3개

푼 문제


백준 #13163. 닉네임에 갓 붙이기: 문자열 / 브론즈3

🚩플로우 (선택)

코드를 풀이할 때 적었던 플로우가 있나요?

  • 문자열을 공백을 기준으로 split 하기
  • split하여 구분된 것 중에 1번째부터 다시 문자열로 합친 후 맨 앞에 god 합치기

🚩제출한 코드

n = int(input())

for i in range(n):
    name = input().split()
    god = 'god' + ''.join(name[1:])
    print(god)

백준 #1755. 숫자놀이 : 문자열 / 실버4

🚩플로우 (선택)

코드를 풀이할 때 적었던 플로우가 있나요?

  1. 초기화 작업을 진행한다.
    1. 숫자를 영어로 변환하기 위한 리스트 english를 준비한다.
      이 리스트는 숫자 0부터 9까지의 영단어를 저장한 리스트이다. 인덱스로 구분하여 저장한다. 예를 들어 0번째 인덱스에는 zero, 1번째 인덱스에는 one, … 9번째 인덱스에는 nine으로 english 리스트에 저장한다.
    2. 이 문제를 풀기 위해 답이 되어 반환할 딕셔너리 answer를 빈 딕셔너리로 초기화한다.
    3. 시작 범위 m과 끝 범위 n을 입력받는다.
    4. m에서 n까지의 숫자 리스트를 nums에 저장한다.
  2. nums 리스트를 순회하며 해당 하는 값에 몫과 나머지를 각각 english 리스트를 사용하 영단어로 변환하여 temp에 저장한다.
  3. 변환된 temp 문자열을 answer 딕셔너리에 num을 키로 하여 저장한다.
  4. 사전순으로 정렬한 후에 출력한다.
    1. answer 딕셔너리의 items()value를 기준으로 정렬하여 출력한다.
    2. cnt 변수를 사용해 출력된 숫자의 개수를 세고, 10개를 출력할 때마다 줄바꿈을 한다.

🚩제출한 코드

import sys
input = sys.stdin.readline

# 숫자 0부터 9까지의 영어 표현을 리스트에 저장
english = ["zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine"]
answer = {} # 결과를 저장할 딕셔너리 (key: 숫자, value: 영어 표현)

m, n = map(int, input().split())
nums = list(range(m, n+1)) # m ~ n까지의 숫자 리스트

# 숫자를 영어로 변환하여 사전에 저장
for num in nums:
    temp = ""
    if num // 10 > 0:  # 십의 자리 숫자가 존재하는 경우
        temp += english[num // 10] + " "
    temp += english[num % 10]
    answer[num] = temp # 딕셔너리에 추가
    
# 사전순으로 정렬 후 10개씩 출력
cnt = 0
for key, value in sorted(answer.items(), key=lambda x:x[1]): # value 값을 기준으로 오름차순 정렬
    cnt += 1
    print(key, end=" ")
    if cnt == 10: # 10개 출력할 때마다 줄바꿈
        print()
        cnt = 0

💡TIL

배운 점이 있다면 입력해주세요

  • 나는 이 문제에 대해 쓸데없이 좀 장황하게 풀긴 했다..

  • 자꾸 자꾸 lambda를 이용하여 정렬하는 부분을 까먹는다. 꼭 기억하자 메모.

    >>> for key, value in sorted(pi.items(), key=lambda x:-x[1]):
    >>>     pi_list.append(key+":"+str(value))
    >>> pi_list
    # ['cc:9', 'bb:5', 'c:4', 'a:3', 'b:1', 'aa:1']

백준 #16173. 점프왕 쩰리 (Small) : DFSBFS / 실버4

🚩플로우 (선택)

코드를 풀이할 때 적었던 플로우가 있나요?

  1. 게임 구역의 크기 n을 입력받고 게임판의 구역(맵)을 jump_game 리스트에 저장한다.
  2. BFS 탐색을 시작한다.
    1. queue에 출발점을 추가한 후, 오른쪽과 아래 방향으로 현재 위치의 칸 수 만큼 이동한다.
    2. 맵 범위 안에 있고, 아직 방문하지 않은 경우에는, 방문 표시를 하고 queue에 추가한다.
    3. 탐색 중에 도착점에 도달했다면, BFS 탐색을 종료하고 True를 반환한다.
    4. 탐색할 queue가 더이상 없는 경우에는, False를 반환한다.
  3. BFS 탐색 결과가 True 이면 “HaruHaru”를, False 이면 “Hing”을 출력한다.

🚩제출한 코드

import sys
from collections import deque
input = sys.stdin.readline

def bfs(x, y, n):
    queue = deque()
    queue.append((x, y)) # 시작점 추가
    visited[x][y] = True # 초기 방문 처리

    while queue:
        x, y = queue.popleft()
        for dx, dy in [(0, jump_game[x][y]), (jump_game[x][y], 0)]: # 아래 (0, jump), 오른쪽 (jump, 0)
            nx, ny = x + dx, y + dy  # 현재 위치에서 칸 수만큼 이동
            # 맵 범위 안에 있고, 아직 방문하지 않은 경우
            if 0 <= nx < n and 0 <= ny < n and not visited[nx][ny]:
                if jump_game[nx][ny] == -1:  # 도착 지점에 도달하면
                    return True
                visited[nx][ny] = True
                queue.append((nx, ny))  # 다음 이동 지점 추가

    return False

# 입력 처리
n = int(input())
jump_game = []
visited = [[False for _ in range(n)] for _ in range(n)]
for _ in range(n):
    temp = list(map(int, input().split()))
    jump_game.append(temp)

# BFS 탐색
if bfs(0, 0, n):
    print("HaruHaru")
else:
    print("Hing")

💡TIL

배운 점이 있다면 입력해주세요

  • dx, dy 경로 정의에 시간을 많이 소비했다. 방향을 결정하는 조건을 문제에 맞게 설정을 해야 한다는 것을 알게 되었다.
    • 처음에는 기존 방식대로 dx, dy를 정의했는데, 오른쪽과 아래로만 이동할 수 있으므로 1이 아닌 현재 위치의 값만큼 이동해야 한다는 점을 깨달았다.
    • Y축 이동에서 아래로 이동할 때 +를 사용해야 함에도 불구하고, 잘못해서 ``로 작성하는 실수를 했다. 좌표 이동 방향을 정확히 파악하는 것이 중요하다.
    • dx, dy 설정을 외우기보다는 문제에 맞게 응용하는 것이 중요함을 배웠다.
  • 상단에 초기 방문 처리하는 부분은 잊지말자
  • 사소하지만 파이썬에서 False인지 판단할 때는 변수==False라고 쓰는 것보다는 not 변수 이렇게 쓰는 게 더 파이써닉하고 깔끔한 것 같다.
  • 파이썬에서 조건문에서 == False 대신 not을 사용하는 것이 더 파이써닉하고 깔끔하다.

백준 #1072. 게임: 이분탐색 / 실버3

🚩플로우 (선택)

코드를 풀이할 때 적었던 플로우가 있나요?

  1. 전체 게임 수(x)와 이긴 게임 수(y) 입력 받아 현재 승률 z를 계산한다.
  2. 이때 z가 99이상이면 더이상 승률이 변하지 않으므로, -1을 출력하고 프로그램을 종료한다.
  3. 99 미만일 경우 이분탐색을 통해 최소 게임 수를 찾는다.
    1. left는 1, rightx로 설정하고, leftright보다 작거나 같은 동안 이분 탐색을 진행한다.
    2. left는 1, rightx로 설정한다. leftright를 기준으로 left값이 right값보다 작거나 같을 경우에 대해 이분 탐색을 진행한다.
    3. 중간값 mid를 다시 계산한 후, 추가 게임을 했을 때의 새로운 승률을 계산한다.
    4. 추가 게임 후의 승률이 변하지 않으면, 더 많은 게임을 추가해야 하므로 left를 증가시킨다.
    5. 승률이 변한다면, 해당 mid 값을 정답(answer)로 설정하고, right를 줄여 더 적은 게임으로 승률이 변할 수 있는지 확인한다.
  4. 이분 탐색이 종료되면 최종적으로 구한 최소 게임 수인 answer를 출력한다.

🚩제출한 코드

import sys
input = sys.stdin.readline

x, y = map(int, input().split())  # 전체 게임 수(x)와 이긴 게임 수(y) 입력
z = y // x * 100  # 현재 승률 z 계산

if z >= 99:  # 만약 승률이 99% 이상이면 더 이상 승률을 변화시킬 수 없으므로 -1 출력 후 종료
    print(-1)
    exit(0)

answer = 0
left = 1  # 이분 탐색의 시작값 설정
right = x  # 이분 탐색의 끝값 설정

while left <= right:  # 이분 탐색 시작
    mid = (left + right) // 2  # 중간 값 계산
    if ((y + mid) * 100) // (x + mid) <= z:  # 추가한 게임 후 승률 계산
        left = mid + 1  # 승률이 변하지 않으면 더 많은 게임을 추가해야 하므로 left 증가
    else:
        answer = mid  # 승률이 변하면 해당 mid 값을 저장하고
        right = mid - 1  # 더 적은 게임에서 승률이 변할 수 있는지 확인하기 위해 right 감소

print(answer)  # 최종적으로 구한 최소 게임 수 출력

💡TIL

배운 점이 있다면 입력해주세요

  • 이 문제를 처음에 봤을 때는 수학적으로 접근해야 하는 줄 알았다. 근데 아무리봐도 어떤 규칙으로 접근해야 할 지 감이 오지 않았다. 99클럽에서 제공하는 힌트를 보았더니 **이분탐색**이라고 나와있었다. 이 문제가 왜 이분탐색인지 한참을 고민했던 것 같다. 이 문제를 계기로 이분탐색에 대해 복습할 수 있었다.

    • **이분탐색**할 때는 leftright의 범위를 올바르게 설정해주어야 한다. 그리고 left를 언제 이동시켜야 하는지 right를 언제 시켜야 하는지 그 조건(=**탐색 범위를 줄여가는 조건)**도 함께 생각해주어야 한다.
  • Z에 대해 구하기 위해서 z = y // x * 100로 풀었는데 틀렸다고 나왔다. 예제를 돌렸을 때는 이상이 없었는데 왜 안 되는지 이유를 몰랐다. 결국 다른 분의 풀이를 보고 z = (y * 100) // x 로 고쳤더니 해결되었다. 이유는 연산 순서에 있었다.

    • y = 8이고, x = 10인 경우를 들어보겠다.
      1. z = y // x * 100
        • y // x = 8 // 10 = 0 (정수 나눗셈이기 때문에 소수점 이하를 버림)
        • 0 * 100 = 0
        • 결과적으로 승률이 0으로 잘못 계산된다
      2. z = (y * 100) // x
        • 먼저 y * 100 = 8 * 100 = 800
        • 그 다음 800 // 10 = 80 (정수 나눗셈이므로 소수점 이하 버림)
        • 결과적으로 정확한 승률인 80이 계산된다.

    기존 방식은 먼저 소수점을 버려버리기 때문에 잘못된 계산이 나올 수밖에 없었던 것이다. 실수자료형은 무한 소수가 나올 수 있는데, 컴퓨터 연산의 메모리는 이를 정확히 커버할 수가 없어 예상과는 다른 결과가 나올 수 있다. 이 부분에 대해 새로 알게 되었다.

    참고자료:


백준 #2252. 줄 세우기: 위상정렬,그래프 / 골드3

🚩플로우 (선택)

코드를 풀이할 때 적었던 플로우가 있나요?

  • 입력 처리
    • 학생 수 n, 키 비교 횟수 m을 입력받는다.
    • 빈 그래프 graph와 모든 학생의 진입차수를 0으로 초기화한 indegree 리스트를 생성한다.
      • graph: 각 학생의 키 비교 관계를 저장 (a번 학생이 b번 학생보다 앞에 서야 하면, a -> b 형태로 연결).
      • indegree: 각 학생이 앞에 있어야 하는 학생들의 수를 저장 (즉, 진입 차수).
  • 간선 정보 입력
    • m번 반복하여 a, b 학생의 키 비교 정보를 입력받는다.
    • ab보다 앞에 서야 하므로 graph[a]b를 추가하고, indegree[b]를 1 증가시킨다.
  • 위상 정렬 함수 정의 (topology_sort)
    • 최종적으로 학생들을 정렬한 순서를 저장할 리스트 result를 선언한다.
    • 현재 진입 차수가 0인 학생들을 담는 큐qdeque 사용해 초기화한다.
  • 초기 큐 설정
    • 모든 학생에 대해 indegree[i]가 0인 학생들을 큐에 넣는다.
      • 즉, 다른 학생보다 앞에 서야 할 학생이 없는 학생들을 찾는다.
  • 큐에서 학생을 처리하며 위상 정렬 수행
    • 큐가 빌 때까지 다음을 반복한다.
      • 큐에서 진입 차수가 0인 학생을 꺼내고, now에 저장하고 이를 결과 리스트에 추가한다.
      • now 학생과 연결된 모든 학생들의 진입 차수를 1씩 감소시킨다.
      • 진입 차수가 0이 된 학생은 다시 큐에 삽입한다.
      • 이 과정은 진입 차수가 0이 되는 학생들만 큐에 들어가므로, 순서대로 정렬된다.
  • 결과 출력
    • 모든 학생을 처리한 후, result 리스트에 저장된 학생들을 출력한다.
    • 위상 정렬에 의해 순서가 결정된 학생들이 출력된다.

🚩제출한 코드

import sys
from collections import deque
input = sys.stdin.readline

n, m = map(int, input().split()) # 학생 수, 학생순서
graph = [[] for _ in range(n + 1)] # 학생 순서 그래프
table = [0] * (n+1) # 진입차수표

for _ in range(m):
    a, b = map(int, input().split())
    graph[a].append(b)
    table[b] += 1

# 큐로 구현
queue = deque()
for i in range(1, n+1):
    # 진입차수표가 0인 경우 큐에 삽입
    if table[i] == 0:
        queue.append(i)

# 큐가 빌 때까지 진행
while queue:
    now = queue.popleft()
    for i in graph[now]:
        table[i] -= 1 # 1씩 제거
        # 진입차수가 0인 값은 큐에 다시 삽입
        if table[i] == 0:
            queue.append(i)
    print(now, end=" ")

💡TIL

배운 점이 있다면 입력해주세요
위상정렬이 마냥 어렵기만 했는데 차근차근 위상정렬에 대해 공부한 후 문제에 적용하니까 좀 이해가 되었다. 위상정렬의 조건과 위상정렬만이 가지고 있는 특징을 이해하게 되었다. 앞으로 이 내용을 토대로 단계별로 문제를 풀어나가봐야겠다.

@github-actions
Copy link

github-actions bot commented Apr 8, 2025

2025-04 챌린지 진행 상황

사용자 챌린지 유형 문제 수 달성 여부
Mingguriguri 그래프 3
Mingguriguri DP 6
zaqquum 그래프 0
zaqquum DP 2
learntosurf 그래프 2
learntosurf DP 3

@Mingguriguri Mingguriguri merged commit b15132e into main Apr 11, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants