Skip to content

Conversation

@zaqquum
Copy link
Collaborator

@zaqquum zaqquum commented Sep 14, 2025

🌱WIL

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

  • 이번 주는 LCS나 냅샙문제 등 DP의 대표적인 문제 유형들을 풀어보았다. 여전히 문제 속 규칙 찾고 점화식을 세우는 과정까지가 어렵지만 이제는 DP 문제가 등장해도 어렵지 않게 접근 할 수 있을 것 같다.

🚀주간 목표 문제 수: 4개

푼 문제


프로그래머스 #12905. 가장 큰 정사각형 찾기: DP / level2

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

🚩플로우 (선택)

  • if board[i][j] == 1 이면
    -> dp[i,j] = min( (i-1,j), (i,j-1) , (i-1,j-1)) + 1 대입

참고자료 : https://ddiyeon.tistory.com/60

🚩제출한 코드

def solution(board):
    answer = 0
    dp = [[0]*len(board[0]) for _ in range(len(board))]
    #1. 반복문으로 board[i,j] 찾기
    for i in range(len(board)):
        for j in range(len(board[0])):
            if board[i][j] == 1 :  
            #2. dp로 (i,j)을 정사각형 오른쪽 아래 칸으로 가지는 최대 변의 길이 구하기
                if 0<=i-1<=len(board) and 0<=j-1 < len(board[0]):
                    dp[i][j] = min(dp[i-1][j] , dp[i][j-1] , dp[i-1][j-1]) +1 
                    # print(dp[i][j])
                    
                else :
                    dp[i][j] = 1
                answer= max(answer , dp[i][j])
                
    # print(dp)
    # print(answer)
    return answer**2

백준 #1926. 그림: 그래프/ 실버1

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

🚩플로우 (선택)

  1. 그림 개수 구하기
    1. 전체 칸(i,j)을 기준점으로 BFS/DFS 함수 반복 횟수로 연결된 그래프 개수 구하기
  2. 최대 그림 넓이
    1. 그래프 탐색시 각 그래프에서 방문한 노드의 개수 확인하고 그중 최대 값 구하기

🚩제출한 코드

"""
[BOJ]#1826.그림
https://www.acmicpc.net/problem/1926
# problem
- 그림은 1로 가로,세로(대각선x) 연결됨
- 그림 넓이 = 1의 개수 (0:여백)
-goal) 전체 nxm 도화지 속 (1) 그림 개수 (2)그림들 중 최대 넓이 
  *없으면 0 0 출력
# flow
1. 그림 개수 구하기 
  i. 전체 칸(i,j)을 기준점으로 BFS/DFS로 연결된 그래프 더미 찾기

2. 최대 그림 넓이
  - 그래프 탐색시 각 그래프에서 방문한 노드의 개수 확인&최대값 저장하기 
"""

import sys
from collections import deque
# 1. 입력 변수 - 전체 도화지 크기 / 도화지 속 그림 위치 정보
input = sys.stdin.readline
N,M = map(int, input().split())

canvas = [[0]*M for _ in range(N)]
for i in range(N):
  canvas[i] = list(map(int, input().split()))
# print(canvas)
# 그림 개수 /최대 그림 넓이 변수 선언
pic_cnt = 0 
pic_area = 0 

#2. 전체 도화지 칸을 탐색하며서 BFS로 그림들 연결하기
def bfs(start):
  # 해당 노드 1 의 개수, 방문한 노드 위치 정보 -> canvas 의 0으로 기입
  one_cnt = 0 # start 초기화
  q =deque([start])
  canvas[start[0]][start[1]] = 0  
  dy = [-1,1,0,0] # 상하좌우 이동 가능 
  dx = [0,0,-1,1]

  while q :
    cy,cx = q.popleft()
    one_cnt +=1  #그림 넓이 추가 
 
    for d in range(4):
      ny,nx= cy+dy[d], cx +dx[d]
 
      if 0<=ny<N and 0<= nx <M and canvas[ny][nx] == 1 : # 범위 내, 그림 범위임
        q.append([ny,nx])
        canvas[ny][nx]=0

  return one_cnt 

#3. 전체 칸을 BFS탐색 시작점으로 순회하기

for i in range(N) :
  for j in range(M):
    if canvas[i][j] == 1 : #그림이면,BFS 탐색 시작
      area=bfs([i,j])
      # 그림 최대 넓이 업데이트하기
      if area > 0 : # 그림이 존재하면, 그림 개수 +1 & 넓이 최대값 업데이트
        pic_cnt += 1 
        pic_area = max(pic_area,area)

print(pic_cnt)
print(pic_area)

💡TIL

-기본적인 그래프 탐색 알고리즘 문제이다.

백준 #5567. 결혼식: 그래프/ 실버2

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

🚩플로우 (선택)

2다리 이하 친구 관계만 초대 -> 총 인원수 파악

  1. 양방향 인접 리스트 만들기
  2. level =2 을 제한한 BFS 탐색하기(level=3, 강제 종료)
  3. 지금까지 방문한 노드 개수 출력

🚩제출한 코드

"""
https://www.acmicpc.net/problem/5567

"""
import sys
from collections import deque
#1.양방향 인접 리스트 만들기
input =sys.stdin.readline

N = int(input())
M = int(input())
friends = [[] for _ in range(N+1)] # 1~ n 번까지
for i in range(1,M+1):
  x,y = map(int, input().split())
  friends[x].append(y)
  friends[y].append(x)

#2. lv2 이하인 BFS 가즈아~
start = 1 
q = deque([[start,0]]) # 학번, 관계 거리
visited = [start]
answer =-1
while q : 
  cnum , crelationship= q.popleft()
  if crelationship >= 3: 
    break # 거리가3 넘으면 강제종료
  answer +=1 
  # print(f"#{cnum} : {crelationship}")
  for nn in friends[cnum] :
    if nn not in visited : 
      q.append([nn, crelationship+1])
      visited.append(nn)
      
# print(visited)
print(answer)

백준 #24501. blobaww: DP/ 골드3

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

🚩플로우 (선택)

image
  1. 알파벳 보드 입력받기와 E 와 M 의 위치 및 누적합를 나타내는 행렬 정의 ( 있으면 1, 없으면 0 으로 초기화)

    1. e_sum : E 의 누적합
    2. m_sum : M의 누적합
  2. E와 M 행렬 누적합 계산하기

    dp[i][j] = dp[i-1][j] + dp[i][j-1] -dp[i-1][j-1 + value[i][j]

    1. E의 누적합 계산하기
    2. M의 누적합 계산하기
  3. soomi jeong / 3월 3주차 / 3문제  #3. S 을 기준으로 총 경우의 수 구하기

경우의 수 = E의 M 의 곱

`answer += e_sum[y][x]*m_sum[y][x]`
  1. 최종 경우의 수를 10^7 +7로 나눈 나머지로 출력

🚩제출한 코드

import sys
answer =0 
N, M = map(int, sys.stdin.readline().split())
board =[[] for _ in range(N)]
# E와 M의 누적합 행렬 정의
e_sum = [[0]*M for _ in range(N)]
m_sum = [[0]*M for _ in range(N)]

for i in range(N):
    board[i] = list(sys.stdin.readline()[:-1])
    for j in range(M):
        if board[i][j] == "E" :
            e_sum[i][j] = 1
        elif board[i][j] == "M" : 
           m_sum[i][j] = 1

# 2.E와 M 행렬 누적합 계산하기
# dp[i][j]  = dp[i-1][j] + dp[i][j-1] -dp[i-1][j-1 + value[i][j]
for i in range(N):
   for j in range(M):
      # E의 누적합 계산
        # i=0 or j=0 일때 누적합 점화식
        if i==0 and j== 0 : 
            e_sum[0][0] = e_sum[0][0]
        elif i== 0 : # 가로형 누적합 계산식 : 
            e_sum[i][j] = e_sum[0][j-1]+e_sum[0][j]
        elif j == 0: # 세로형 누적합 계산식
            e_sum[i][j] = e_sum[i][0] + e_sum[i-1][0]
        else : # 일반적인 누적합 계산식
            e_sum[i][j] = e_sum[i-1][j] + e_sum[i][j-1] - e_sum[i-1][j-1] + e_sum[i][j]

#M의 누적합 계산 : E의 누적합의 역방향(아래로 뒤집기) 
# 기준(i,j) : 왼쪽 위쪽 칸    
for i in range(N-1, -1 , -1):
    for j in range(M-1 , -1 ,-1) :
    # i=0 or j=0 일때 누적합 점화식
        if i== N-1 and j== M-1 : # 맨 오른쪽 아래 칸의 누적합
            m_sum[i][j] = m_sum[i][j]
        elif i== N-1 : # 가로형 누적합 계산식 : 
            m_sum[i][j] = m_sum[i][j+1]+m_sum[i][j]
        elif j == M-1 : # 세로형 누적합 계산식
            m_sum[i][j] = m_sum[i][j] + m_sum[i+1][j]
        else : # 일반적인 누적합 계산식
            m_sum[i][j] = m_sum[i+1][j] + m_sum[i][j+1] - m_sum[i+1][j+1] + m_sum[i][j]

#3. S 을 기준으로 총 경우의 수 구하기
# 경우의 수 = E*M
answer = 0 
for y in range(N):
    for x in range(M):
        # S 의 위치 파악하기
        if board[y][x] == "S" :
            # (y,x) 인 S의 기준에서 E*M 으로 경우의 수 구하기 
            answer += e_sum[y][x]*m_sum[y][x]


#4. 나머지로 출력하기
print(answer%(10**9+7))

💡TIL

[누적합 알고리즘]
i. 배열 An에서 인덱스 0 ~특정 인덱스 i 까지 구간합을 구하는 문제이다.
ii. 전체 요소의 단순 반복 합이 아닌 ** 이전 인덱스 (i-1) 까지의 누적합 + 현재 자신 i의 값** 으로 구현한다.

Sum(An[: idx]) = Sum(An[: idx-1]) + An(idx) 

백준 #9251. LCS: DP/ 골드5

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

🚩플로우 (선택)

image 0. LCS 의 2차원 행렬 0으로 초기화 1. a[i] VS b[j] 문자 비교하기 (1) SAME(=) -> dp[i][j] = 위쪽 대각선 +1 (2) DIFF(!=) -> dp[i][j] = MAX(왼쪽 , 위쪽)
  1. 최종 LCS = dp[-1][-1]

🚩제출한 코드

"""
[BOJ]#9251.LCS / DP /Gold5/ 2025.09.09
https://www.acmicpc.net/problem/9251
#####

"""
import sys
input = sys.stdin.readline
# 1. 입력 변수 - a 문자열 / b문자열
a = list(input())[:-1]
b= list(input())[:-1]
# LCS 행렬 0 초기화
lcs = [[0]*(len(b)+1) for _ in range(len(a)+1)]

#2. LCS (Longest Common Subsequence) 점화식
"""
i. a[i] VS b[j] 문자 비교하기
  (1) SAME(=) -> dp[i][j] = 위쪽 대각선 +1 
  (2) DIFF(!=) -> dp[i][j] = MAX(왼쪽 , 위쪽)

ii. 최종 LCS = dp[-1][-1]
"""
for i in range(1,len(a)+1) :
  for j in range(1, len(b)+1) :
    if a[i-1] == b[j-1]:
      lcs[i][j] = lcs[i-1][j-1] + 1
    else :
      lcs[i][j] = max(lcs[i-1][j] , lcs[i][j-1])

# print(lcs)
print(lcs[-1][-1])

💡TIL

-Longest Common Subsequence : 연속적인 공통 문자열 찾기

백준 #12865. 평범한 배낭_2try: DP/ 골드5 (재도전)

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

🚩플로우 (선택)

. 입력 변수 입력받기

  • 물품 총 개수 / 제한 무게 / 물건별 무게 w, 가치 v
  1. DP 정의

    • 최대가치 DP[k][i]: 최대 K kg 제한을 가진 가방안에 0~ i번쨰 item 까지 탐색 후 최대 가치
  2. 배낭의 제한 무게를 0K 씩 , 물건의 탐색 범위 0N로 반복하여 DP 점화식 계산하기

    1. 물건 w > 배낭 무게제한 k : 물건 i는 배낭에 못 넣을 때 최대가치

      dp[k][i] = dp[k][i-1]

    2. 물건 w <= 배낭 무게제한 k : MAX(물건 i를 넣을 때 , 물건 i를 안 넣을 때)

      dp[k][i] = max(item[v] + dp[k-w][i-1],dp[k][i-1])

  3. 최종 배낭 제한이 K 일때, 최대 가치 출력 = dp[K][N]

🚩제출한 코드

"""
[BOJ]평범한 배낭
https://www.acmicpc.net/problem/12865
"""

import sys
input  =sys.stdin.readline
#1. 입력 변수 - 물품 총 개수 / 제한 무게 / 물건별 무게 w, 가치 v
N , K = map(int,input().split()) 
items = [[] for _ in range(N+1)]
for i in range(1,N+1):
  items[i] = list(map(int, input().split()))
# print(items)
#2. DP : 0-1 Knapsack 문제
# DP[k][i]: 최대 K kg 제한을 가진 가방안에 0~ i번쨰 item 까지 탐색 후 최대 가치
#(물건 w > 배낭 무게 k) dp[k][i] = dp[k][i-1] #물건i는 못 넣음
#(물건 w <= 배낭 무게 k) dp[k][i] = max(item[v] + dp[k-w][i-1],dp[k][i-1]) # 물건i를 넣거나(배낭 K-item 무게 만큼의 최대값 + 물건 i 넣기) , 안넣거나

dp = [[0]*(N+1) for _ in range(K+1)]
for k in range(1,K+1) :
  for i in range(1, N+1):
    if items[i][0] <= k : 
      dp[k][i] = max(dp[k-items[i][0]][i-1] + items[i][1],dp[k][i-1] )
    else :
      dp[k][i] =dp[k][i-1]

# print(dp)
#3. dp[-1][-1] = 최종 배낭 K kg에서 최대 가치 출력
print(dp[-1][-1])

💡TIL

[0-1 Knapsap problem 문제]
image

@zaqquum zaqquum self-assigned this Sep 14, 2025
@zaqquum zaqquum merged commit 45be0bb into main Sep 17, 2025
@github-actions
Copy link

🔥2025-09 챌린지 진행 상황

👉 그래프

  • zaqquum: 2개 ❌

👉 구현

  • zaqquum: 0개 ❌

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.

2 participants