일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
- 이메일인증
- 브실이의입시전략
- 쪽지기능
- Gmail인증
- 앱개발
- 코테
- springboot
- 깊이우선탐색
- 노드개발자
- 백준
- 프로그래머스
- static final
- 너비우선탐색
- Java
- email인증
- DFS
- 코딩테스트
- 노드프로젝트
- 자바
- 노드개발
- Python
- 코딩
- 알고리즘
- 파이썬
- nodejs
- SWEA
- 실버5
- 1260
- BFS
- 백준 2667
- Today
- Total
데옹의 블로그
[Python/파이썬] 백준 2667 : 단지번호붙이기 (+ 전 코드 리뷰) 본문
이 문제는 보자마자 걍 DFS로 풀어야겠다는 생각을 했습니다.
바로 풀어봅시다.
처음에 한 생각은 들어가서 집을 철거해버리고 철거한 만큼의 수를 세어 리스트에 저장하면 되겠다 싶었습니다.
철거해버리면 다음에 그 곳을 셀 필요가 없어지니까요 ㅋㅋ ^_^
위 사진이 정말 적절하다고 생각해서 첨부해봤어요... 철거 해버리면 다시 dfs로 탐색할 때 탐색 못 하니까요.
분명 있었는데... 사라졌으니까 갯수를 셀 수가 없죠...
(visited를 사용하지 않아도 되는 이유가 됩니다)
암튼 이 단순한 생각을 그냥 코드로 끄적여봤습니다.
from collections import deque
import sys
input = sys.stdin.readline
n = int(input())
def dfs(x,y):
global cnt
# 범위를 벗어났을 때
if x < 0 or x >= n or y < 0 or y >= n:
return
# 집일 때
if graph[x][y] == 1:
# 일단 갯수 세고
cnt += 1
# 집 철거
graph[x][y] = 0
# 상하좌우 탐색
for i in range(4):
nx = x + dx[i]
ny = y + dy[i]
dfs(nx,ny)
graph = []
for _ in range(n):
graph.append(list(map(int, input().rstrip())))
result = []
cnt = 0
# 상 / 하 / 좌 / 우
dx = [0,0,-1,1]
dy = [1,-1,0,0]
# i,j를 이용해 모든 곳을 확인해봅시다.
for i in range(n):
for j in range(n):
# 집 있으면 철거하러 가보자~
if graph[i][j] == 1:
# 철거 시작 ㅋㅋ
dfs(i,j)
# 철거 완료
# 저장합시다.
result.append(cnt)
cnt = 0
# sort
ans = sorted(result)
print(len(result))
for i in ans:
print(i)
전 개인적으로 주석만으로 설명이 될 것 같다고 생각해요... 그냥 하나하나 철거를 해버리는거죠!!
그래서 이걸 BFS론 어떻게 하냐면...
from collections import deque
import sys
input = sys.stdin.readline
n = int(input())
def bfs(x,y):
queue = deque()
queue.append([x,y])
# 집 철거
graph[x][y] = 0
# 이미 우리는 x,y의 위치를 철거 했습니다. 따라서 cnt도 1 추가하고 시작합시다.
cnt = 1
while queue:
x,y = queue.popleft()
# 집 철거 (처음에 철거한 부분은 신경쓰지 마세요)
graph[x][y] = 0
for i in range(4):
nx = x + dx[i]
ny = y + dy[i]
# 내 관할 아니면 넘어가자
if nx < 0 or ny < 0 or nx >= n or ny >= n:
continue
# 집이 남아있네
if graph[nx][ny] == 1:
# 철거하고
graph[nx][ny] = 0
# 이 집과 관련된 것들까지 털어갈테니 명단에 넣어줍시다.
queue.append([nx,ny])
# 업적 남기기
cnt += 1
return cnt
graph = []
for _ in range(n):
graph.append(list(map(int, input().rstrip())))
result = []
# 상 / 하 / 좌 / 우
dx = [0,0,-1,1]
dy = [1,-1,0,0]
for i in range(n):
for j in range(n):
if graph[i][j] == 1:
cnt = bfs(i,j)
result.append(cnt)
ans = sorted(result)
print(len(result))
for i in ans:
print(i)
DFS 전 코드와 비교하며 리뷰하기
이번엔 제가 전에 풀었던 코드와 새로 푼 코드를 비교하며 설명을 적어볼게요.
어차피 제가 보려고 만든 블로그니까요 ㅋㅋ
전엔 코드의 상하좌우를 for문으로 하지 않고 하나하나 다 썼었습니다. 그 것 외에도 다른 점이 좀 있는데 뭐가 다른지 함 봐보도록 하겠습니다.
우선 그냥 중요한 부분들만 보면서 비교를 해봅시다.
기존의 코드
def dfs(x,y):
if x <= -1 or y <= -1 or x >= n or y >= n:
return False
global cnt
if graph[x][y] == 1:
cnt += 1
graph[x][y] = 0
dfs(x-1,y)
dfs(x,y-1)
dfs(x+1,y)
dfs(x,y+1)
return True
return False
## 기타 코드들
for i in range(n):
for j in range(n):
if graph[i][j] == 1:
dfs(i,j)
result.append(cnt)
cnt = 0
새로운 코드
def dfs(x,y):
global cnt
if x < 0 or x >= n or y < 0 or y >= n:
return
# 집일 때
if graph[x][y] == 1:
cnt += 1
graph[x][y] = 0
for i in range(4):
nx = x + dx[i]
ny = y + dy[i]
dfs(nx,ny)
## 기타 코드들
for i in range(n):
for j in range(n):
if dfs(i,j) == True:
result.append(cnt)
cnt = 0
도대체 어떤 점이 다를까요.. (상하좌우 설정 빼고요)
그냥 딱 보면 모르겠습니다. return이 빠져있군요.. 그리고 DFS를 사용하기 위한 for문도 다른 것을 볼 수 있습니다.
for문 부터 함 비교를 해봅시다.
## 기존의 코드
for i in range(n):
for j in range(n):
# i,j가 return값으로 True를 받았다면
if dfs(i,j) == True:
result.append(cnt)
cnt = 0
## 새로운 코드
for i in range(n):
for j in range(n):
# i,j의 위치가 집이라면
if graph[i][j] == 1:
dfs(i,j)
result.append(cnt)
cnt = 0
# 두 코드 모두 i,j로 모든 지도를 탐색할 수 있도록 하였습니다.
조건이 좀 다릅니다. 여기서 확인하기엔 좀 무리가 있는 것 같습니다. 이제 중요한 DFS부분 비교를 해보겠습니다.
## 기존의 코드
def dfs(x,y):
# 만약 범위를 벗어났다면
if x <= -1 or y <= -1 or x >= n or y >= n:
# False 반환해서 뭐하려고 한거지..
return False
global cnt
# 집일 때
if graph[x][y] == 1:
# 하나 세어주고
cnt += 1
# 집 다신 못 세도록 철거
graph[x][y] = 0
dfs(x-1,y)
dfs(x,y-1)
dfs(x+1,y)
dfs(x,y+1)
return True
return False
## 새로운 코드
def dfs(x,y):
global cnt
# 만약 범위를 벗어났다면
if x < 0 or x >= n or y < 0 or y >= n:
# 돌아가
return
# 집일 때
if graph[x][y] == 1:
# 하나 세어주고
cnt += 1
# 집 다신 못 세도록 철거
graph[x][y] = 0
for i in range(4):
nx = x + dx[i]
ny = y + dy[i]
dfs(nx,ny)
기능의 차이는 없지만...
기존의 코드는 그냥 DFS함수로 무작정 들어갑니다. 집이 있든 말든 말이죠 ㅋㅋㅋㅋㅋ
그래서 들어간 다음에 집이 없으면 그냥 False를 들고 나와요!
집이 있으면 모든 집을 철거한 뒤에 그 수를 저장하고 True를 반환해줍니다. 일단 집이 있으면 세보겠다 이거죠.
[행동파]
새로운 코드는 일단 처음부터 집이 있어야 DFS 함수로 들어갑니다.
들어간 뒤에 다른 곳들을 철거하기 시작하죠.
[효율파]
딱히 다른 건 없습니다. 이게 끝이었네요.. 개인적으로 그냥 볼 땐 새로운 코드가 이해하기 쉽네요.
근데 백준에 넣어보니 코드는 40ms 로 새로운 코드의 68ms보다 기존 코드가 더 빠릅니다. 기존의 코드도 아래 더보기에 첨부하도록 하겠습니다.
n = int(input())
def dfs(x,y):
if x <= -1 or y <= -1 or x >= n or y >= n:
return False
global cnt
if graph[x][y] == 1:
cnt += 1
graph[x][y] = 0
dfs(x-1,y)
dfs(x,y-1)
dfs(x+1,y)
dfs(x,y+1)
return True
return False
graph = []
cnt = 0 # 집 개수를 세는 변수
result = [] # 각각의 집 개수를 넣을 리스트
for i in range(n):
graph.append(list(map(int,input())))
for i in range(n):
for j in range(n):
if dfs(i,j) == True:
result.append(cnt)
cnt = 0
result = sorted(result)
print(len(result))
for i in result:
print(i)
'python' 카테고리의 다른 글
[Python] 프로그래머스 - 공원 산책 [level 1] (0) | 2024.01.12 |
---|---|
[Python] 프로그래머스 - 튜플 (level 2) (2) | 2023.11.09 |
[SWEA] 19003. 펠린드롬 문제(D3) (8) | 2023.11.08 |
[Python/파이썬] 백준 2606 : 바이러스 (0) | 2023.06.18 |
[Python/파이썬] 백준 1260 : DFS와 BFS (0) | 2023.06.17 |