diff --git a/jimin/week3/BOJ1012.py b/jimin/week3/BOJ1012.py new file mode 100644 index 0000000..513d83e --- /dev/null +++ b/jimin/week3/BOJ1012.py @@ -0,0 +1,99 @@ +# 시간 복잡도 : O(N × M) +# 쓰는 방법 : dfs +# 이유 : 모든 케이스를 조사해서 군집이 몇개 있는지 확인할 수 있기 때문 + +# 전체 풀이 방법 +# 1.테스트 케이스 개수를 받기 +# 2.각 테스트 케이스마다 M*N크기의 filed를 만들고 배추 위치는 1로표시 +# 3. 밭 전체를 돌면서 1을 만나면 dfs실행 +# 4. DFS가 한 번 실행될 때마다 지렁이 수를 1 늘려줌 + +# dfs 함수 +# 1.stack에 처음 탐색할 위치 넣어주기 +# 2. 탐색할 위치는 filed에서 0으로 바꿔주기(방문한 배추는 0으로 바꾸기) +# 3. 네 방향을 차례대로 확인한다. +# 4.(nx, ny)가 밭 범위 안에 있고, 아직 방문하지 않은 배추(1)라면: 방문 처리(field[ny][nx] = 0),스택에 (nx, ny) 추가 +# + +import sys + +input = sys.stdin.readline + + +def dfs(start_x, start_y, field, n, m): + stack = [(start_x, start_y)] + field[start_y][start_x] = 0 # 방문 처리 + + directions = [(1, 0), (-1, 0), (0, 1), (0, -1)] + + while stack: + x, y = stack.pop() + for dx, dy in directions: + nx, ny = x + dx, y + dy + if 0 <= nx < m and 0 <= ny < n and field[ny][nx] == 1: + field[ny][nx] = 0 + stack.append((nx, ny)) + + +def solve(M, N, K, cabbage_list): + field = [[0] * M for _ in range(N)] + + # 배추 위치 심기 + for X, Y in cabbage_list: + field[Y][X] = 1 + + worms = 0 + for y in range(N): + for x in range(M): + if field[y][x] == 1: + dfs(x, y, field, N, M) + worms += 1 + return worms + + +def main(): + cases = [ + { + "M": 10, + "N": 8, + "K": 17, + "cabbage_list": [ + [0, 0], + [1, 0], + [1, 1], + [4, 2], + [4, 3], + [4, 5], + [2, 4], + [3, 4], + [7, 4], + [8, 4], + [9, 4], + [7, 5], + [8, 5], + [9, 5], + [7, 6], + [8, 6], + [9, 6], + ], + "expected": 5, + }, + { + "M": 10, + "N": 10, + "K": 1, + "cabbage_list": [[5, 5]], + "expected": 1, + }, + ] + + for i, tc in enumerate(cases): + result = solve(tc["M"], tc["N"], tc["K"], tc["cabbage_list"]) + assert ( + result == tc["expected"] + ), f"[{i}] 실패: expected={tc['expected']}, actual={result}" + print(f"test [{i}] 성공") + + +if __name__ == "__main__": + main() diff --git a/jimin/week3/BOJ1303.py b/jimin/week3/BOJ1303.py new file mode 100644 index 0000000..ee71766 --- /dev/null +++ b/jimin/week3/BOJ1303.py @@ -0,0 +1,59 @@ +def solve(board: list, n, m): + + def dfs(board, visited, x, y): + visited[y][x] = True + num = 0 + for i in range(4): + nx = x + dx[i] + ny = y + dy[i] + if ( + 0 <= nx < n + and 0 <= ny < m + and not visited[ny][nx] + and board[y][x] == board[ny][nx] + ): + num += dfs(board, visited, nx, ny) + return num + 1 + + dx = [0, 0, 1, -1] + dy = [1, -1, 0, 0] + visited = [[False] * n for _ in range(m)] + w_sum = 0 + b_sum = 0 + for y in range(m): + for x in range(n): + if not visited[y][x]: + num = dfs(board, visited, x, y) + num *= num + if board[y][x] == "W": + w_sum += num + else: + b_sum += num + return w_sum, b_sum + + +def main(): + cases = [ + { + "n": 5, + "m": 5, + "board": [ + "WBWWW", + "WWWWW", + "BBBBB", + "BBBWW", + "WWWWW", + ], + "expected": (130, 65), + } + ] + for i, tc in enumerate(cases): + result = solve(tc["board"], tc["n"], tc["m"]) + assert tc["expected"] == result, ( + f"[{i}] 실패: " f"expected={tc['expected']}, actual_result={result}, " + ) + print(f"test [{i}] 성공") + + +if __name__ == "__main__": + main() diff --git a/jimin/week3/BOJ16173.py b/jimin/week3/BOJ16173.py new file mode 100644 index 0000000..ad6dffc --- /dev/null +++ b/jimin/week3/BOJ16173.py @@ -0,0 +1,74 @@ +# 시간복잡도 : O(n²) +# dfs사용해서 풀기 이유 : 모든 경로중에서 끝 지점에 도달하는게 뭔지 찾아야해서 +# 1.게임판을 2차원 리스트로 입력받음 +# 출발점 (0,0)에서 시작해 DFS(스택)를 이용해 탐색 +# 스택에서 좌표를 꺼내 범위를 벗어나면 무시 +# 이미 방문한 좌표도 무시하고, 방문하지 않았다면 방문 처리 +# 현재 칸에 적힌 숫자(점프할 칸 수) 확인 +# 오른쪽, 아래쪽으로 점프 가능한 칸을 스택에 추가 +# 해당 칸이 -1이면 도착 성공 → "HaruHaru" 출력 +# 스택이 다 빌 때까지 도착점을 못 찾으면 실패 → False 반환 + + +def a(board, n): + # 방문 여부를 기록할 2차원 배열 (처음엔 전부 False) + visited = [[False] * n for _ in range(n)] + # DFS를 위한 스택, 출발점 (0,0)에서 시작 + stack = [(0, 0)] + + # 스택이 빌 때까지 반복 + while stack: + # 스택에서 현재 위치를 꺼냄 + x, y = stack.pop() + + # 현재 좌표가 보드 범위를 벗어나면 이 경로는 무효 → 건너뜀 + if x < 0 or y < 0 or x >= n or y >= n: + continue + + # 이미 방문한 좌표라면 다시 방문할 필요 없음 → 건너뜀 + if visited[x][y]: + continue + + # 처음 방문했으므로 방문 처리 + visited[x][y] = True + + # 현재 칸이 도착점(-1)이라면 성공 → True 반환 + if board[x][y] == -1: + return True + + # 현재 칸에 적힌 숫자(점프할 칸 수) 확인 + jump = board[x][y] + + # 0이면 이동할 수 없으므로 더 탐색 불가 → 건너뜀 + if jump == 0: + continue + + # 오른쪽, 아래쪽으로 점프 가능한 칸을 스택에 추가 + stack.append((x, y + jump)) # 오른쪽 이동 + stack.append((x + jump, y)) # 아래쪽 이동 + + # 스택이 다 빌 때까지 도착점을 못 찾으면 실패 → False 반환 + return False + + +def solve(n, board): + return "HaruHaru" if a(board, n) else "Hing" + + +def main(): + cases = [ + {"n": 2, "board": [[0, 96], [50, -1]], "expected": "Hing"}, + {"n": 3, "board": [[1, 1, 1], [1, 1, 1], [1, 1, -1]], "expected": "HaruHaru"}, + {"n": 3, "board": [[2, 2, 1], [2, 2, 1], [1, 1, -1]], "expected": "HaruHaru"}, + {"n": 2, "board": [[0, 1], [1, -1]], "expected": "Hing"}, + ] + for i, tc in enumerate(cases, 1): + result = solve(tc["n"], tc["board"]) + assert ( + tc["expected"] == result + ), f"[{i}] 실패: expected={tc['expected']}, actual_result={result}" + print(f"test [{i}] 성공") + + +if __name__ == "__main__": + main() diff --git a/jimin/week5/BJ_24482.py b/jimin/week5/BJ_24482.py new file mode 100644 index 0000000..0a9d10f --- /dev/null +++ b/jimin/week5/BJ_24482.py @@ -0,0 +1,42 @@ +import sys + +input = sys.stdin.readline +sys.setrecursionlimit(10**6) +INF = sys.maxsize + + +def solve(board: list, n, m, r): + board = [sorted(_list, reverse=True) for _list in board] + visited = [-1] * (n + 1) + + def dfs(board, node, depth): + visited[node] = depth + for i in board[node]: + if visited[i] == -1: + dfs(board, i, depth + 1) + + dfs(board, r, 0) + return visited[1:] + + +def main(): + cases = [ + { + "n": 5, + "m": 5, + "r": 1, + "board": [[], [4, 2], [1, 3, 4], [2, 4], [1, 2, 3], []], + "expect": [0, 3, 2, 1, -1], + } + ] + + for i, tc in enumerate(cases, 1): + result = solve(tc["board"], tc["n"], tc["m"], tc["r"]) + assert result == tc["expect"], ( + f"[{i}] 실패: " f"expected={tc['expected']}, actual_result={result}, " + ) + print(f"test [{i}] 성공") + + +if __name__ == "__main__": + main() diff --git a/jimin/week5/BJ_24483.py b/jimin/week5/BJ_24483.py new file mode 100644 index 0000000..a7ad757 --- /dev/null +++ b/jimin/week5/BJ_24483.py @@ -0,0 +1,50 @@ +import sys + +input = sys.stdin.readline +sys.setrecursionlimit(10**6) +INF = sys.maxsize + + +def solve(board: list, n, m, r): + board = [sorted(_list) for _list in board] + visited = [[-1, 0] for _ in range(n + 1)] + order = 1 + + def dfs(board, node, depth): + nonlocal order + visited[node][0] = depth + visited[node][1] = order + order += 1 + for i in board[node]: + if visited[i][1] == 0: + dfs(board, i, depth + 1) + + dfs(board, r, 0) + sum = 0 + for a, b in visited[1:]: + sum += a * b + + return sum + + +def main(): + cases = [ + { + "n": 5, + "m": 5, + "r": 1, + "board": [[], [4, 2], [1, 3, 4], [2, 4], [1, 2, 3], []], + "expect": 20, + } + ] + + for i, tc in enumerate(cases, 1): + result = solve(tc["board"], tc["n"], tc["m"], tc["r"]) + assert result == tc["expect"], ( + f"[{i}] 실패: " f"expected={tc['expected']}, actual_result={result}, " + ) + print(f"test [{i}] 성공") + + +if __name__ == "__main__": + main() diff --git a/jimin/week5/BJ_31575.py b/jimin/week5/BJ_31575.py new file mode 100644 index 0000000..77d29f1 --- /dev/null +++ b/jimin/week5/BJ_31575.py @@ -0,0 +1,75 @@ +# 도시가 M행 × N열의 격자로 주어짐 +# 1 → 지나갈 수 있는 칸 +# 0 → 건물이라 못 가는 칸 +# 시작 위치: (0,0) (좌상단) +# 도착 위치: (M-1, N-1) (우하단) +# 이동은 오른쪽(→) 또는 아래쪽(↓) 으로만 가능 +# 도착 가능하면 "Yes", 아니면 "No" +def solve_item(N, M, grid): + # 방문 여부 + visited = [[False] * N for _ in range(M)] + + # 시작 위치 (항상 1이라고 보장됨) + stack = [(0, 0)] + visited[0][0] = True + + # DFS (스택 사용) + while stack: + x, y = stack.pop() + + # 도착지에 도달하면 True 반환 + if x == M - 1 and y == N - 1: + return "Yes" + + # 이동 가능한 방향: 오른쪽, 아래 + for dx, dy in [(0, 1), (1, 0)]: + nx, ny = x + dx, y + dy + + # 범위 안에 있고, 갈 수 있는 칸(1), 아직 방문 X + if 0 <= nx < M and 0 <= ny < N: + if grid[nx][ny] == 1 and not visited[nx][ny]: + visited[nx][ny] = True + stack.append((nx, ny)) + + # 끝까지 못 갔으면 No + return "No" + + +def main(): + cases = [ + { + "name": "예제 입력 1 (가능한 경우)", + "N": 5, + "M": 4, + "grid": [ + [1, 1, 1, 1, 1], + [0, 1, 0, 0, 1], + [1, 0, 0, 0, 1], + [0, 0, 0, 1, 1], + ], + "expected": "Yes", + }, + { + "name": "갈 수 없는 경우", + "N": 3, + "M": 3, + "grid": [ + [1, 0, 0], + [0, 0, 0], + [0, 0, 1], + ], + "expected": "No", + }, + ] + + for i, tc in enumerate(cases, 1): + actual_result = solve_item(tc["N"], tc["M"], tc["grid"]) + assert actual_result == tc["expected"], ( + f"[{i}] {tc['name']} 실패: " + f"expected={tc['expected']}, actual={actual_result}" + ) + print(f"[{i}] {tc['name']} 성공") + + +if __name__ == "__main__": + main()