본문 바로가기

코딩테스트/Baekjoon

[JAVA] 백준 5212번: 지구 온난화

< 문제 >

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

package silver;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.StringTokenizer;

public class P5212 {
	// 지구 온난화
	static char origin[][]; //원본 배열
	static char changed[][];//바뀐 배열 
	static int R, C;
	
	//상하좌우가 바다인지 확인하고 3면 이상이 바다이면 바다로 바꾸는 함수 
	static void check(int x, int y) { 
		int cnt = 0;

		if (x < 1)
			cnt++;
		else {
			if (origin[x - 1][y] == '.') // 상
				cnt++;
		}

		if (x > R - 2)
			cnt++;
		else {
			if (origin[x + 1][y] == '.') // 하
				cnt++;
		}

		if (y <= 0)
			cnt++;
		else {
			if (origin[x][y - 1] == '.') // 좌
				cnt++;
		}

		if (y > C - 2)
			cnt++;
		else {
			if (origin[x][y + 1] == '.') // 우
				cnt++;
		}

		if (cnt >= 3) // 만약 바다가 3개 이상이면
			changed[x][y] = '.'; // 바다로 바꿈
	}

	public static void main(String[] args) throws IOException {
		// TODO Auto-generated method stub
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		StringTokenizer st = new StringTokenizer(br.readLine());

		R = Integer.parseInt(st.nextToken()); // 세로
		C = Integer.parseInt(st.nextToken()); // 가로
		origin = new char[R][C];
		changed = new char[R][C];

		for (int i = 0; i < R; i++) {
			String s = br.readLine();
			for (int j = 0; j < C; j++) {
				origin[i][j] = s.charAt(j); // 배열에 값을 저장 
			}
		}

		for (int i = 0; i < R; i++) {
			for (int j = 0; j < C; j++) {
				changed[i][j] = origin[i][j]; // 2차원 배열은 clone 함수로 깊은 복사 안됨
			}
		}

		for (int i = 0; i < R; i++) {
			for (int j = 0; j < C; j++) {
				if (origin[i][j] == 'X') { // 땅일 경우 
					check(i, j); // 상하좌우 바다인지 확인
				}
			}
		}
		
		// 좁아진 땅 출력을 위해 행의 최솟값 최댓값, 열의 최솟값 최댓값 구하기 
		int rmin=10,rmax=0,cmin=10,cmax=0;
		for (int i = 0; i < R; i++) {
			for (int j = 0; j < C; j++) {
				if (changed[i][j] == 'X') {
					rmin=Math.min(rmin, i);
					rmax=Math.max(rmax, i);
					cmin=Math.min(cmin, j);
					cmax=Math.max(cmax, j);
				}
			}
		}
		
		//출력
		for (int i = rmin; i <=rmax; i++) {
			for (int j = cmin; j <= cmax; j++) {
				System.out.print(changed[i][j]);
			}
			System.out.println();
		}

	}

}

 

✏️ 풀이 방법

 

1. 2차원 배열 origin 에 값을 입력받는다. 

2. 배열 changed 에 origin 배열의 값을 똑같이 저장한다.

3. origin 배열의 값이 'X' 일 경우 ( 땅일 경우) => 상하좌우가 바다인지 확인한다.

    : check 함수 실행 => 상 하 좌 우가 배열의 범위를 넘어갈 경우, 바다이므로 cnt 증가

                                 => 상 하 좌 우의 값이 '.' 일 경우 바다이므로 cnt 증가

                                 => cnt 의 값이 3 이상이면, 즉 3면 이상이 바다로 둘러싸여있으면 changed 배열의 해당 위치를 바다로 변경

4. 작아진 지도의 크기를 구하기 위해, 값이 'X' 일 경우의 행 열의 최솟값과 최댓값을 구한다.

5. 행의 최소~ 최대, 열의 최소~ 최대에 해당하는 땅을 출력한다. 

 

✍🏻 느낀점

 

이런 유형의 문제를 너무 오랜만에 풀어봐서 입력받는것조차 까먹었다 ㅋㅋㅋㅋㅋ,, 당황한,, 그리고 check 함수에서 범위를 어떻게 설정해야할지 생각을 잘못해서 이 부분에서 뻘짓을 너무 많이 했다. 배열의 맨 마지막 인덱스는 [R-1][C-1]인데, 이것을 생각 못하고 R과 C로 계산해서 제대로 된 결과가 출력되지 않았다 ㅜㅜ 그리고,, 좁아진 땅을 계산하기 위해 최대 최소를 구해야 하는건 알겠는데 이것을 어떻게 할까 list에 넣어서 해야하나 고민하다가 너무 복잡해질 것 같아서 다른 블로그를 참고해서 문제를 풀었다. 엉엉.. 이 문제 나는 왜 이렇게까지 복잡하게 푼건지 모르겠다,, 여러 방면에서 내 부족한 점을 깨닫게 해준 문제였다. 

 

 

 

 

참고 블로그


https://bacchus-lover.tistory.com/469

https://hanyeop.tistory.com/366 // 2차원 배열은 냅다 clone 하면 깊은 복사 안됨, 즉 동일한 주솟값을 가지게 됨