본문 바로가기
백준/탐색(BFS, DFS)

백준 2636, 2638번 치즈

by 기초백과 2021. 1. 14.

 

www.acmicpc.net/problem/2636

 

2636번: 치즈

아래 <그림 1>과 같이 정사각형 칸들로 이루어진 사각형 모양의 판이 있고, 그 위에 얇은 치즈(회색으로 표시된 부분)가 놓여 있다. 판의 가장자리(<그림 1>에서 네모 칸에 X친 부분)에는 치즈가 놓

www.acmicpc.net

www.acmicpc.net/problem/2638

 

2638번: 치즈

첫째 줄에는 모눈종이의 크기를 나타내는 두 개의 정수 N, M (5≤N, M≤100)이 주어진다. 그 다음 N개의 줄에는 모눈종이 위의 격자에 치즈가 있는 부분은 1로 표시되고, 치즈가 없는 부분은 0으로 표

www.acmicpc.net

너비 우선 탐색의 대표 문제 치즈입니다.

다른 분들이 푼 문제들 순서대로 정리해놓은 것들 보았을때 자주 본 기억이 있네요.

좋은 문제인듯 해요~~

 

예전에 처음 풀려고 시도했을때 분명 성공률은 높은데

도저히 생각이 안나서 포기했었던 기억이 납니다만

다시 해보니 아주 어렵지는 않은 문제였네요ㅎㅎ;

 

2636번에서 한 가지 조건이 추가된 문제가 2638번인데요.

그렇기에 2636번을 먼저 풀고 2638번을 풀었더니 수월하게 해결할 수 있었습니다.

 

구현한 부분은 다음과 같습니다.

  • BFS를 통한 탐색 및 치즈 리스트 저장
  • 치즈 리스트에서의 조건문을 통해 녹일 치즈와 녹이지 않을 치즈 결정
  • 각 시간 마다 녹지 않은 치즈 갯수 최신화
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.Queue;
import java.util.StringTokenizer;

public class Cheeze2638 {
	int height, width, cheezeNum = 0, deleteCount, time;
	ArrayList<Point> cheezeList = new ArrayList<>();
	Queue<Point> surfaceQueue = new LinkedList<>();
	int[][] map;
	boolean[][] isNotVisted;
	boolean canDelete;
	int[] xDir = { 0, 0, -1, 1 };
	int[] yDir = { -1, 1, 0, 0 };

	public class Point {
		int x, y;

		public Point(int y, int x) {
			// TODO Auto-generated constructor stub
			this.x = x;
			this.y = y;
		}
	}

	public void bfsCheeze() {
		int i, j, x, y, queueSize;
		Point nowPoint;
		for (i = 0; i < height; i++)
			Arrays.fill(isNotVisted[i], true);

		surfaceQueue.add(new Point(0, 0));
		isNotVisted[0][0] = false;
		deleteCount = 0;
		time++;
		
		while (!surfaceQueue.isEmpty()) {
			nowPoint = surfaceQueue.remove();

			for (i = 0; i < 4; i++) {
				x = nowPoint.x + xDir[i];
				y = nowPoint.y + yDir[i];

				if (x >= 0 && x < width && y >= 0 && y < height && map[y][x] == 0 && isNotVisted[y][x]) {
					surfaceQueue.add(new Point(y, x));
					isNotVisted[y][x] = false;
				}else if (x >= 0 && x < width && y >= 0 && y < height && map[y][x] == 1 && isNotVisted[y][x]) {
					cheezeList.add(new Point(y, x));
					isNotVisted[y][x] = false;
				}
			}
		}
		
		int checkCount;
		for(Point tmp : cheezeList) {
			checkCount = 0;
			for (i = 0; i < 4; i++) {
				x = tmp.x + xDir[i];
				y = tmp.y + yDir[i];
				
				if(x >= 0 && x < width && y >= 0 && y < height && map[y][x] == 0 && !isNotVisted[y][x]) {
					checkCount++;
				}
			}
			
			if(checkCount >= 2) {
				isNotVisted[tmp.y][tmp.x] = true;
				map[tmp.y][tmp.x] = 0;
				deleteCount++;
			}
		}
		cheezeList.clear();
		
		cheezeNum -= deleteCount;
		if(cheezeNum == 0)
			canDelete = false;
	}

	public void setNum() throws IOException {
		int i, j;

		BufferedReader bf = new BufferedReader(new InputStreamReader(System.in));
		StringTokenizer st = new StringTokenizer(bf.readLine());

		height = Integer.parseInt(st.nextToken());
		width = Integer.parseInt(st.nextToken());

		map = new int[height][width];
		isNotVisted = new boolean[height][width];
		canDelete = true;
		time = 0;
		
		for (i = 0; i < height; i++) {
			st = new StringTokenizer(bf.readLine());
			for (j = 0; j < width; j++) {
				map[i][j] = Integer.parseInt(st.nextToken());
				if (map[i][j] == 1)
					cheezeNum++;
			}
		}
	}

	public static void main(String[] args) throws IOException {
		// TODO Auto-generated method stub
		Cheeze2638 main = new Cheeze2638();
		main.setNum();
		
		while(main.canDelete) {
			main.bfsCheeze();
		}
		System.out.println(main.time);
		//System.out.println(main.deleteCount);
	}

}

반성할 점

  • 포인트 클래스 만들지 말고 쓰기!
  • dir 배열로 BFS를 FOR문으로 돌리기!

 

'백준 > 탐색(BFS, DFS)' 카테고리의 다른 글

백준 11559번 PuyoPuyo  (0) 2021.01.17
백준 2583번 영역 구하기  (0) 2021.01.14
백준 2468번 안전 영역  (0) 2021.01.14
백준 14502번 연구소  (0) 2021.01.13
백준 16236번 아기상어  (0) 2021.01.13