본문 바로가기
코딩테스트 준비/JAVA 코테

백준1012. 유기농배추 DFS, BFS

by 김긍수 2021. 3. 23.

www.acmicpc.net/problem/1012

 

1012번: 유기농 배추

차세대 영농인 한나는 강원도 고랭지에서 유기농 배추를 재배하기로 하였다. 농약을 쓰지 않고 배추를 재배하려면 배추를 해충으로부터 보호하는 것이 중요하기 때문에, 한나는 해충 방지에 

www.acmicpc.net

문제제목 : 유기농배추

문제유형 : BFS, DFS

문제난이도 : 실버2

문제

차세대 영농인 한나는 강원도 고랭지에서 유기농 배추를 재배하기로 하였다. 농약을 쓰지 않고 배추를 재배하려면 배추를 해충으로부터 보호하는 것이 중요하기 때문에, 한나는 해충 방지에 효과적인 배추흰지렁이를 구입하기로 결심한다. 이 지렁이는 배추근처에 서식하며 해충을 잡아 먹음으로써 배추를 보호한다. 특히, 어떤 배추에 배추흰지렁이가 한 마리라도 살고 있으면 이 지렁이는 인접한 다른 배추로 이동할 수 있어, 그 배추들 역시 해충으로부터 보호받을 수 있다.

(한 배추의 상하좌우 네 방향에 다른 배추가 위치한 경우에 서로 인접해있다고 간주한다)

한나가 배추를 재배하는 땅은 고르지 못해서 배추를 군데군데 심어놓았다. 배추들이 모여있는 곳에는 배추흰지렁이가 한 마리만 있으면 되므로 서로 인접해있는 배추들이 몇 군데에 퍼져있는지 조사하면 총 몇 마리의 지렁이가 필요한지 알 수 있다.

예를 들어 배추밭이 아래와 같이 구성되어 있으면 최소 5마리의 배추흰지렁이가 필요하다.

(0은 배추가 심어져 있지 않은 땅이고, 1은 배추가 심어져 있는 땅을 나타낸다.)

1 1 0 0 0 0 0 0 0 0
0 1 0 0 0 0 0 0 0 0
0 0 0 0 1 0 0 0 0 0
0 0 0 0 1 0 0 0 0 0
0 0 1 1 0 0 0 1 1 1
0 0 0 0 1 0 0 1 1 1

입력

입력의 첫 줄에는 테스트 케이스의 개수 T가 주어진다. 그 다음 줄부터 각각의 테스트 케이스에 대해 첫째 줄에는 배추를 심은 배추밭의 가로길이 M(1 ≤ M ≤ 50)과 세로길이 N(1 ≤ N ≤ 50), 그리고 배추가 심어져 있는 위치의 개수 K(1 ≤ K ≤ 2500)이 주어진다. 그 다음 K줄에는 배추의 위치 X(0 ≤ X ≤ M-1), Y(0 ≤ Y ≤ N-1)가 주어진다.

출력

각 테스트 케이스에 대해 필요한 최소의 배추흰지렁이 마리 수를 출력한다.

 

아이디어

  • 연결 요소의 개수를 세는 문제
  • 모든 정점에 대하여 DFS나 BFS를 수행하고 한번 방문한 정점은 확인하지않는다.
  • 전체적으로 DFS나 BFS의 총 수행횟수를 계산한다.

배추(x, y)와 이어져있는 배추의 위치는?

1. (x+1, y)

2. (x-1, y)

3. (x, y+1)

4. (x, y-1)

이렇게 4가지가 될 수 있다.

4개의 위치 중 배추가 심어져있는 위치로 가서 다시 그 위치와 이어져있는 배추가 있는지 탐색을 하면 된다.

 

DFS코드1

문제만 보고 혼자 푼 코드!

package week4;

import java.io.BufferedReader;
import java.io.InputStreamReader;

public class BOJ1012 {
	private static int[][] field;
	private static int count;
	
	public static void main(String[] args) throws Exception {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		
		int T = Integer.parseInt(br.readLine());
		
		for (int test = 0; test < T; test++) {
			String[] input = br.readLine().split(" ");
			int M = Integer.parseInt(input[0]); //밭 가로길이
			int N = Integer.parseInt(input[1]); //밭 세로길이
			int K = Integer.parseInt(input[2]); //배추 개수
			
			// 배열초기화
			field = new int[M][N];
			
			//배추심기
			for (int i = 0; i < K; i++) {
				String[] location_K = br.readLine().split(" ");
				int x = Integer.parseInt(location_K[0]);
				int y = Integer.parseInt(location_K[1]);
				
				field[x][y] = 1;
			}
			
			count = 0;
			
			for (int i = 0; i < N; i++) {
				for (int j = 0; j < M; j++) {
					if (field[i][j] == 1) {
						DFS(i, j);
						count++;
					}
				}
			}
			System.out.println(count);
		}
	}
	
	public static void DFS(int x, int y) {
		if (field[x][y] == 0) return;
		
		field[x][y] = 0;
		
		if (x + 1 < field.length && field[x + 1][y] == 1) {
			DFS(x+1, y);
		}
		
		if (x - 1 >= 0 && field[x - 1][y] == 1) {
			DFS(x-1, y);
		}
		
		if (y + 1 < field[0].length && field[x][y + 1] == 1) {
			DFS(x, y+1);
		}
		
		if (y - 1 >= 0 && field[x][y - 1] == 1) {
			DFS(x, y-1);
		}
	}
}

DFS코드2

블로그 답을 참고하여 다시 작성한 코드!!

package week4;

import java.io.BufferedReader;
import java.io.InputStreamReader;

public class BOJ1012_2 {

	private static int T, M, N, K;
	private static int[][] field;
	public static boolean[][] visited;
	private static int count;
	private static int[] dx = {-1, 1, 0, 0};
	private static int[] dy = {0, 0, -1, 1};
	
	public static void main(String[] args) throws Exception {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		
		T = Integer.parseInt(br.readLine());
		
		for (int test = 0; test < T; test++) {
			String[] input = br.readLine().split(" ");
			M = Integer.parseInt(input[0]); //밭 가로길이
			N = Integer.parseInt(input[1]); //밭 세로길이
			K = Integer.parseInt(input[2]); //배추 개수
			
			// 배열초기화
			field = new int[M][N];
			visited = new boolean[M][N];
			
			//배추심기
			for (int i = 0; i < K; i++) {
				String[] location_K = br.readLine().split(" ");
				int x = Integer.parseInt(location_K[0]);
				int y = Integer.parseInt(location_K[1]);
				
				field[x][y] = 1;
			}
			
			count = 0;
			for (int i = 0; i < M; i++) {
				for (int j = 0; j < N; j++) {
					if (field[i][j] == 1 && !visited[i][j]) {
						DFS(i, j);
						count++;
					}
				}
			}
			System.out.println(count);
		}
	}
	
	public static void DFS(int x, int y) {
		visited[x][y] = true;
		
		for (int i = 0; i < 4; i++) {
			int nx = x + dx[i];
			int ny = y + dy[i];
			
			if (nx < 0 || nx >= M || ny < 0 || ny >= N) { // 값이 범위에 맞는지 확인
				continue;
			}
			if(field[nx][ny] == 1 && !visited[nx][ny]) {
				DFS(nx, ny);
			}
		}
	}
}

 

BFS코드

package week4;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.LinkedList;
import java.util.Queue;

public class BOJ1012_BFS {
	private static int[][] field;
	private static boolean[][] visited;
	private static int count;
	private static int T, M, N, K;
	private static int dx[] = {-1, 1, 0, 0};
	private static int dy[] = {0, 0, -1, 1};

	public static void main(String[] args) throws Exception {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		
		T = Integer.parseInt(br.readLine());
		
		for (int test = 0; test < T; test++) {
			String[] input = br.readLine().split(" ");
			M = Integer.parseInt(input[0]); 
			N = Integer.parseInt(input[1]); 
			K = Integer.parseInt(input[2]); 
			
			// 배열초기화
			field = new int[M][N];
			visited = new boolean[M][N];
			
			//배추심기
			for (int i = 0; i < K; i++) {
				String[] location_K = br.readLine().split(" ");
				int x = Integer.parseInt(location_K[0]);
				int y = Integer.parseInt(location_K[1]);
				
				field[x][y] = 1;
			}
			
			count = 0; // 벌레 수
			
			for (int i = 0; i < M; i++) {
				for (int j = 0; j < N; j++) {
					if (field[i][j] == 1 && !visited[i][j]) {
						BFS(i, j);
						count++;
					}
				}
			}
			System.out.println(count);
		}
	}
	
	// 너비탐색
	public static void BFS(int x, int y) {
		Queue<Location> q = new LinkedList<>();
		Location d = new Location(x, y);
		q.add(d);
		visited[x][y] = true;
		
		while (!q.isEmpty()) {
			Location now = q.poll();
			
			for (int i = 0; i < 4; i++) {
				int a = now.x + dx[i];
				int b = now.y + dy[i];
				
				if (a < 0 || b < 0 || a >= M || b >= N) {
					continue; 
				}
				
				if (!visited[a][b] && field[a][b] == 1) {
					// 방문하지 않았고 해당 위치에 배추가 있으면
					q.add(new Location(a, b));
					visited[a][b] = true;
				}

			}	
			
		}
		
	}
}

class Location {
	int x;
	int y;
	
	Location(int x, int y) {
		this.x = x;
		this.y = y;
	}
}

추가학습

2차원 배열 int[][] field = new int[10][5]; 일때

(행 길이) field.length == 10;

(열 길이) field[0].length == 5;

'코딩테스트 준비 > JAVA 코테' 카테고리의 다른 글

백준2667. 단지번호붙이기 (BFS, DFS)  (0) 2021.03.25
백준1325. 효율적인 해킹 DFS, BFS  (0) 2021.03.24
백준 1697. 숨바꼭질  (0) 2021.03.22
백준 2606. 바이러스  (0) 2021.03.22
백준 2164. 카드2  (0) 2021.03.08

댓글