[BOJ]#4963 섬의 개수 Python

현지·2021년 3월 24일
0

BOJ

목록 보기
11/44

문제

https://www.acmicpc.net/problem/4963

정사각형으로 이루어져 있는 섬과 바다 지도가 주어진다. 섬의 개수를 세는 프로그램을 작성하시오.

한 정사각형과 가로, 세로 또는 대각선으로 연결되어 있는 사각형은 걸어갈 수 있는 사각형이다.

두 정사각형이 같은 섬에 있으려면, 한 정사각형에서 다른 정사각형으로 걸어서 갈 수 있는 경로가 있어야 한다. 지도는 바다로 둘러싸여 있으며, 지도 밖으로 나갈 수 없다.

입력

입력은 여러 개의 테스트 케이스로 이루어져 있다. 각 테스트 케이스의 첫째 줄에는 지도의 너비 w와 높이 h가 주어진다. w와 h는 50보다 작거나 같은 양의 정수이다.

둘째 줄부터 h개 줄에는 지도가 주어진다. 1은 땅, 0은 바다이다.

입력의 마지막 줄에는 0이 두 개 주어진다.

출력

각 테스트 케이스에 대해서, 섬의 개수를 출력한다.

아이디어

  1. w,h를 0이 아닐때까지 반복해서 입력 받는다.
  2. bfs를 함수를 이용한다.
  3. 주어진 입력을 for문을 이용해서 1이 있는 곳을 찾는다.
  4. 1이면 queue에 넣고, visited를 True로 변경한다.
  5. queue에서 하나씩 꺼내 상, 하, 좌, 우, 대각선 모두를 검사해서 1이 있으면 4번을 반복한다.
  6. queue에 더 이상 값이 없으면 cnt에 하나 더해준다.

내 코드(Python)

import sys
from collections import deque

def bfs(data):
    queue=deque()
    #상,하,좌,우,대각선 모두 검사
    a=[0, 0, 1, -1, 1, -1, 1, -1]
    b=[1, -1, 0, 0, 1, -1, -1, 1]
    cnt=0   #섬 개수
    for i in range(h):	#처음 1이 있는 곳 찾기
        for j in range(w):
       	    #1이고 방문하지 않은경우
            if data[i][j]==1 and visited[i][j] == False:	
                queue.append(i)
                queue.append(j)
                visited[i][j]=True
                while queue:	#queue가 비어있지 않으면 반복
                    x=queue.popleft()
                    y=queue.popleft()
                    for k in range(0,8):    #자기 기준으로 주변에 1이 있나 검사
                        p=x+int(a[k])   #x+=int(a[k])   => 이렇게 하면 x,y값이 계속 변해서 안됨 => 모든 경우를 다 따질 수 없음
                        q=y+int(b[k])   #y+=int(b[k]) => 안됨
                        if 0<=int(p)<h and 0<=int(q)<w and data[p][q]==1 and visited[p][q]==False:
                            queue.append(p)
                            queue.append(q)
                            visited[p][q]=True
                cnt+=1
    print(cnt)

w, h=map(int, sys.stdin.readline().split())

while (w != 0 and h !=0):
    data=[[x for x in map(int, sys.stdin.readline().split())] for y in range(h)]
    visited=[[False for _ in range(w)] for _ in range(h)]

    bfs(data)

    w, h = map(int,sys.stdin.readline().split())

다른코드(Python)

*deque에 append할 때, q.append((i,j))로 하고 꺼낼때 x,y=q.popleft()로 가져올 수 있음

from _collections import deque

while True:
    w, h = map(int, input().split())
    if w == 0 and h == 0:
        break

    island = [list(map(int, input().split())) for _ in range(h)]

    # 상 우상 우 우하 하 좌하 좌 좌상
    # 8방향 탐색을 위해
    dx = [-1, -1, 0, 1, 1, 1, 0, -1]
    dy = [0, 1, 1, 1, 0, -1, -1, -1]

    # 속도가 빠른 디큐를 사용
    q = deque()
    cnt = 0
    for i in range(h):
        for j in range(w):
            # 먼저 육지인 곳을 찾는다.
            if island[i][j] == 1:
                # 육지를 q에 넣어주고
                q.append((i, j))
                # 방문했다는 표시로 값을 2로 바꿔준다.
                island[i][j] = 2

                while q:
                    # 현재 위치를 q에서 꺼내주고
                    cx, cy = q.popleft()
                    # 8방향 탐색을 해준다.
                    for k in range(8):
                        nx = cx + dx[k]
                        ny = cy + dy[k]
                        # 전체 배열 범위 안에 있으면서
                        if 0 <= nx < h and 0 <= ny < w:
                            # 육지이면 값을 2로 바꿔주고 q에 넣어준다.
                            if island[nx][ny] == 1:
                                q.append((nx, ny))
                                island[nx][ny] = 2

                # 이어져 있는 육지를 다 돌았다면 cnt+1
                else:
                    cnt += 1

    print(cnt)

출처 : https://deok2kim.tistory.com/21

0개의 댓글