Skip to content

Conversation

@zaqquum
Copy link
Collaborator

@zaqquum zaqquum commented Aug 3, 2025

🌱WIL

이번 한 주의 소감을 작성해주세요!

  1. 이번 주는 백트레킹 문제만 골라서 풀었다. 백트레킹 유형은 단독으로 활용하기 보다는 그래프 이론(DFS)나 복잡한 구현 등 융합형 문제들이 많은 것 같다. 이제 백트레킹 문제에 대해선 어느 정도 자신이 생긴 듯 하니 다음 주 부터는 그래프 이론 문제 위주로 풀어 보아야 겠다.

🚀주간 목표 문제 수: 4개

푼 문제


프로그래머스 #81302. 거리두기 확인하기: 백트레킹/ lv2

정리한 링크: (바로가기)

🚩제출한 코드

from collections import deque

dy =[1,-1,0,0] ; dx=[0,0,-1,1]         
def solution(places):
    answer = []
    for place in places : 
        # 1. 응시자 위치 확인 
        people = []
        for i in range(5) :
            for j in range(5) :
                if place[i][j] == "P":
                    people.append([i,j])
        #2. 응시자 별로 거리 확인하기
        def bfs(start):
            clv = 0 
            visited = [[-1]*5 for _ in range(5)] # 거리 저장하기(lv)
            q = deque([start]) 
            visited[start[0]][start[1]] = 0 
            while q  :
                cy,cx = q.popleft()
                clv = visited[cy][cx]
                if clv >= 2 : 
                    break
                for d in range(4):
                    ny,nx = cy + dy[d] , cx +dx[d]
                    if 0<= ny < 5 and 0 <= nx < 5 and visited[ny][nx] <= -1  : 
                        if place[ny][nx] == "X": 
                            visited[ny][nx] = clv +1 
                            continue
                        elif place[ny][nx] == "O":
                            q.append([ny,nx])
                            visited[ny][nx] = clv +1 
                        elif place[ny][nx] == "P" :
                            return False 
            return True 
        flag = True
        for p in range(len(people)):
            start = people[p]
            flag = bfs(start) 
            if not flag : 
                break
        if flag: 
            answer.append(1)
        else :
            answer.append(0)
        
            
    # print(people)
    # print(f"answer{answer}")
    return answer

백준 #2468. 안전영역: DP/ 실버1

정리한 링크: (바로가기)

🚩제출한 코드

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

n = int(input())
field = [] 
limit_list= set()
limit_list.add(0) 
# 1. 물에 잠김, 생존 구역으로 구분한 field 만들기
for i in range(n):
  tmp = list(map(int,input().split()))
  for j in range(n) :
    # limit_list 수집하기 = 노드의 높이 값 종류
    limit_list.add(tmp[j])
  field.append(tmp)
# print(f"field - {limit_list}")

# 종류별 limit에 따라 지대 높이가 limit 이하일 경우 침수되는 지역, 생존 지역 명시
# board :  생존 여부 + 방문 여부 확인 flag 역할
def init_board(limit) :
  # 각 limit 별로 침수되는 지역을 확인하기
  board = [[0 for _ in range(n)] for k in range(n)  ]
  saved_point = []
  # 침수 지역 맵 업데이트하기
  for i in range(n):
    for k in range(n):
      if field[i][k] <= limit : # 침수 지역
        board[i][k] =-1
      else : 
         # 생존 지역
        saved_point.append([i,k])
  return board,saved_point

# 2. 생존 구역들의 군집 개수 구하기 
#상하좌우
dy =[-1,1,0,0 ]
dx = [0,0,-1,1]
def bfs(sy,sx , field): 
  # (1)시작점 정의
  q = deque()
  q.append([sy,sx])
  field[sy][sx] = 1 # 방문 등록
  # (2)인접한 노드 
  while q  : 
    cy,cx =q.popleft()
    for dw in range(4):
      ny,nx = cy + dy[dw] , cx +dx[dw] 
      # 2-1 필드 범위에서 벗어나는지 확인
      # 2-2방문 여부 확인
      if 0<= ny < n and 0<= nx < n and field[ny][nx] == 0 : # 방문 안했으면 업데이트
        q.append([ny,nx])
        field[ny][nx] = 1 
    
  return 0 
# main 함수 
max_cnt = 0 
for limit in limit_list :  #limit 을 1개씩 조합해봄 
  board,saved_point = init_board(limit)
  # print(f"##{limit} : {saved_point}")
  cnt = 0 
  # 생존 구역에서 확인 
  for y,x in saved_point :
    if board[y][x] == 0 :#방문 안했으면 -> bfs 탐색 진행
      bfs(y,x, board)
      cnt +=1 

  max_cnt = max(max_cnt , cnt)
print(max_cnt)

백준 #6603. 로또: 백트레킹 / 실버2

정리한 링크: (바로가기)

🚩플로우 (선택)

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

  1. 입력 변수 정의하기
    • 입력 : K . {K개의 숫자 조합}
  2. backtracking 함수 정의하기
    • 매개 변수

      level : 출력 조합 result에 현재 선택한 원소가 들어갈 위치

      idx : 현재 level 에서 사용 가능한 원소들의 범위 인덱스 idx ~ -1

      → 조합의 경우 , 이전 level(level-1)선택한 원소의 위치 i 보다 뒤에 있는 숫자 조합들 선택하면 된다.

    • 종료 조건

      level == 6 # 출력 배열 result의 원소가 6개를 충족할 경우

    • 함수 정의

      1. level == 6 이면 함수 종료

      2. idx ~ k 범위의 숫자를 출력 변수 result[level] 에 대입

      3. level+1 으로 이동 ,탐색 범위를 idx → i+1 로 이동

        *조합은 현 level에서 선택한 i보다 작은 숫자는 탐색 할 필요 없음

🚩제출한 코드

import sys
input = sys.stdin.readline
# 1. 입력 변수 및 출력 형식에 맞춰 설정하기
while True :
  set_s = list(map(int, input().split()))
  answer = []
  if len(set_s) < 2 : 
    break 
  k= set_s.pop(0)
  #2. 유효성 검사 is_valid 정의
  # check = [True]*len(set_s[1:])
  result = [0]*6 # 출력 리스트
  #3. 백트래킹 함수 정의
  def conbination(level ,idx ): 
    #종료 조건
    if level == 6 : 
      answer.append(result.copy())
      # print(result)
      return 
    # 동작 과정
    for i in range(idx,k):
      result[level] = set_s[i]
      conbination(level+1 ,i+1) # 조합은 idx 보다 작은 i는 탐색 할 필요 없음
      result[level] = 0 
  conbination(0,0)
  # print(answer)
  # 3. 출력 형식 맞추기
  for a in answer: 
    print(" ".join(map(str,a)))
  print("")

백준 #16987. 계란으로 계란치기: 백트레킹/ 골드5

정리한 링크: (바로가기)

🚩플로우 (선택)

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

  • 유형 : Brute force + pruning
    • 계란 선택하는 모든 경우의 수 고려 그 중 최대값
    • 재귀
      [1] backtracking 재귀 함수 상태 매개변수
      선택한 계란idx, 생존 달걀의 idx의 리스트 , 현 내구도 및 무게 상태
      [2] 종료 조건
      (1) 선택 계란 다 선택 했을때 idx >= N 일때
      (2) 남은 계란 다 깼을떄
      => 부순 계란 최대값 반환
      [3] 나머지 동작 과정
      • 선택 계란 i 외 안 꺠진 다른 계란들 선택하기
      • 서로 충돌시키고 남은 내구도 업데이트
      • if 내구도 <1 => 죽음
      • 다름 i+1 & 생존 계란 선택하기

🚩제출한 코드

import sys

#0. 입력 변수 정의 및 초기화 하기
input= sys.stdin.readline
N = int(input())
eggs = [[] for _ in range(N)]

for i in range(N):
  durability , weight =map(int ,input().split())
  eggs[i] = [durability , weight]

# 1. backtracking 수행하기
max_cnt = 0 
def backtracking(idx,cnt) :
  global max_cnt
  print(f"stage {idx}")
  # pruning 조건 : 현재 남은 횟수로 2개씩 깨도  max_cnt 업데이트 불가 경우
  if max_cnt >= (cnt + (N-idx)*2):
    
  #1. 종료 조건 : (1. 모든 계란 선택 완료 n == N)
  if idx >= N : # 1개 이하 남아있을떄 
    max_cnt = max(max_cnt , cnt)
    return 0 
  
  #1-2. 현재 선택한 계란 (idx) 가 깨져있는 경우
  if eggs[idx][0] <= 0 : 
    backtracking(idx+1 , cnt)
  #2.동작 과정- 계란 깨기
  else : # 현재 계란 lived -> 부딫힐 계란 선택 & 부딫치기
    flag =False
    for j in range(N) :#현재 계란 부딫칠 계란 선택 (본인idx 아님 or 생존 )
      if j!= idx and eggs[j][0] > 0 : 
        # 충돌
        eggs[idx] =eggs[idx] -eggs[j][1]
        eggs[j] =eggs[j] -eggs[idx][1]
        backtracking(idx+1 , cnt+int(eggs[idx][0]<=0) + int(eggs[j][0]<=0) ) # 충돌 계산하기
        flag = True
        # 충돌 원상 복귀
        eggs[idx] =eggs[idx] +eggs[j][1]
        eggs[j] =eggs[j] +eggs[idx][1]
    # 한 번도 안 깨짐 -> 선택한 idx 내려두고 다음 idx +1 로 이동  
    if not flag : 
      backtracking(idx+1 , cnt )

  return 0 

backtracking(0 ,0)
print(max_cnt)

##백준 #1230. 문자열 거리: DP/ 골드1
정리한 링크: (바로가기)

🚩제출한 코드

import sys
input = sys.stdin.readline
# 0. 입력 변수 정의 및 초기화 하기
o = list(input())
l = list(input())
INF = 1000
if len(l) < len(o) :
  print(-1)
  exit()
#1. dp 정의
# dp[i][j][0] : de[i][j]로 O[:i] == L[:j]
dp = [[[0,0] for j in range(len(l)+1)] for i in range(len(o)+1)]
# 초기화
dp[0][0] = [0,INF]
for j in range(1,len(l)+1):
  dp[0][j][1] = 1 
  dp[0][j][0] = INF 
# for i in range(len(o)+1):
#   dp[i][0][0] = -1 

# #2. 점화식 
for i in range(len(o)) :
  for j in range(i+1):
    dp[i+1][j][0] = dp[i+1][j][1] = INF
  for j in range(i, len(l)):
    if o[i] == l[j] :
      dp[i+1][j+1][0] = min(dp[i][j][0] , dp[i][j][1])
    else : 
      dp[i+1][j+1][0] = INF 
    dp[i+1][j+1][1] = min(dp[i+1][j][0] +1 , dp[i+1][j][1])
#3. 출력
if min(dp[-1][-1][0],dp[-1][-1][1]) >= INF : 
  print(-1)
else :
  print(min(dp[-1][-1][0] , dp[-1][-1][1]))

Copy link
Member

@YoonYn9915 YoonYn9915 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

한 주 수고하셨습니다!

@zaqquum zaqquum self-assigned this Aug 10, 2025
@zaqquum zaqquum merged commit 77652c8 into main Aug 10, 2025
@github-actions
Copy link

🔥2025-08 챌린지 진행 상황

👉 그리디

👉 구현

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants