| 일 | 월 | 화 | 수 | 목 | 금 | 토 |
|---|---|---|---|---|---|---|
| 1 | 2 | 3 | ||||
| 4 | 5 | 6 | 7 | 8 | 9 | 10 |
| 11 | 12 | 13 | 14 | 15 | 16 | 17 |
| 18 | 19 | 20 | 21 | 22 | 23 | 24 |
| 25 | 26 | 27 | 28 | 29 | 30 | 31 |
- 딕셔너리
- BOJ
- HTTP
- 오버라이딩
- 스택과 힙
- 코딩
- 파이썬
- Merge sort
- 머신러닝
- 캐싱
- 파이썬 오류
- 자바
- 코테
- 백준
- 코딩테스트
- 너비우선탐색
- 멱등
- bineary search
- 알고리즘
- 비지도학습
- 강화학습
- 파이썬 알고리즘
- post
- 지도학습
- 깊이우선탐색
- 프로그래머스
- 해시
- rest api
- 딥러닝
- 이진탐색
- Today
- Total
chae._.chae
[Algorithm] 백준 #4963 - 섬의 개수 본문
https://www.acmicpc.net/problem/4963
4963번: 섬의 개수
입력은 여러 개의 테스트 케이스로 이루어져 있다. 각 테스트 케이스의 첫째 줄에는 지도의 너비 w와 높이 h가 주어진다. w와 h는 50보다 작거나 같은 양의 정수이다. 둘째 줄부터 h개 줄에는 지도
www.acmicpc.net
📌 다시 봐야 할 부분
1. dx, dy를 모두 돌면서 확인해줄 때, 범위 벗어난 처리를 먼저!
if nx < 0 or nx >= w or ny < 0 or ny >= h: # 범위를 벗어난 경우
continue
이 부분을 먼저 적어주어야한다. 범위를 벗어난 경우의 처리를 아래로 빼주고 육지가 아닌 경우나 땅인 경우를 먼저 처리하려고 하면, out of index오류가 발생한다.
주로 다른 bfs문제에서는 상하좌우만을 보면 되는데, 이 문제는 대각선으로 연결되었을때까지 확인해줘야 한다.
상하좌우 + 대각선 연결시 이동가능 -> 아래와 같이 총 8개로 잡아줘야한다
dx = [0, 0, 1, 1, 1, -1, -1, -1]
dy = [-1, 1, -1, 0, 1, -1, 0, 1]
일반적인 상하좌우 문제에서는 dx, dy를 아래처럼 잡아준다.
dx = [-1, 1, 0, 0]
dy = [0, 0, -1, 1]
2. 그리고 나의 삽질
맞게 푼 것 같은데 자꾸 index out of range가 발생해서 살펴보니, 행과 열의 확인 범위를 반대로 적어줬다.....ㅇㅏ..?
for i in range(h):
for j in range(w):
if graph[i][j] == 1: #1(육지)이면
result += 1
bfs(i, j)
while문 안에서 i의 범위는 h이고, j의 범위는 w이므로,
if nx < 0 or nx >= h or ny < 0 or ny >= w: # 범위를 벗어난 경우
이게 맞는거다. h랑 w를 계속 반대로 적어줬다....
3. 방문처리
visited 배열을 만들어서 방문처리를 해주려고 했으나,
bfs함수로 확인을 하면서, 육지 방문시 방문된 것의 표시로 육지(1) -> 바다(0)로 바꿔주는 방법을 사용했다.
📚 코드
import sys
from collections import deque
dx = [0, 0, 1, 1, 1, -1, -1, -1] # 가로, 세로, 대각선 연결시 이동가능 -> 총 9개로 잡아줘야한다
dy = [-1, 1, -1, 0, 1, -1, 0, 1]
def bfs(x, y): # 1이 땅, 0이 바다
queue = deque()
queue.append([x, y])
while queue:
x, y = queue.popleft()
for i in range(8):
nx = x + dx[i]
ny = y + dy[i]
if nx < 0 or nx >= h or ny < 0 or ny >= w: # 범위를 벗어난 경우
continue
if graph[nx][ny] == 0: # 바다인경우 -> 계속하기
continue
if graph[nx][ny] == 1: # 땅인경우
graph[nx][ny] = 0 # visited를 사용하지 않고 방문한 땅은 0으로 바꿔준다!
queue.append([nx, ny]) # 큐에 넣어주기
while True:
w, h = map(int, sys.stdin.readline().rstrip().split()) # 너비, 높이
if (w == 0) and (h == 0):
break
graph=[]
for _ in range(h):
graph.append(list(map(int, sys.stdin.readline().rstrip().split()))) # 지도 입력
# visited = [[False] * w for _ in range(h)]
result = 0
for i in range(h):
for j in range(w):
if graph[i][j] == 1: #1(육지)이면
result += 1
bfs(i, j)
print(result)
+ dfs, bfs 두 방식으로 모두 푸는 것이 가능하다고 한다.
나는 bfs방식으로 풀어서 런타임에러(RecursionError) 가 나지 않았지만, dfs로 푼 경우 이를 위해
sys.setrecursionlimit(100000) 코드를 추가해줘야 한다.
이유 : 파이썬의 재귀 깊이는 기본이 1000으로 설정되어 있는데, 이 문제의 제한에서는 깊이가 최대 2500까지 들어갈 수 있어 문제가 된다고 한다!! (w <= 50, h <=50 범위 확인!)
'파이썬 알고리즘 > BOJ' 카테고리의 다른 글
| [Algorithm] 백준 #1012 - 유기농 배추 (0) | 2022.05.27 |
|---|---|
| [Algorithm] 백준 #2667 - 단지번호붙이기 (0) | 2022.05.27 |
| [Algorithm] 백준 #1946 - 신입사원 (0) | 2022.03.29 |
| [Algorithm] 백준 #2108 - 통계학 (0) | 2022.03.29 |
| # 3048 - 개미 (0) | 2022.01.15 |