알고리즘 스터디 5월 4주차 문제1 (벽 부시고 이동하기4)

문제#

  • 링크로 대체

풀이 및 주저리..

백준 오프라인 수업 도중 설명을 듣고도 풀 때 어렵게 풀었던 문제이다. BFS 뿐만 아니라 Simulation 적인 요소도 잘 섞여 있는 문제라 나름 난이도가 꽤 높았던 문제였다. 그냥 단순하게 벽의 상하좌우에서 BFS 로 값을 구해주다보면 중복적인 부분이 너무 많고 연산시간이 엄청나게 오래걸려 시간 초과가 나는 문제이다. 그렇기 때문에 시작전에 빈곳을 이어 그룹화 시켜주고 그 다음 벽을 부수면서 진행하여 문제를 해결하였다.

코드가 깔끔하지 못해서 마음에 많이 걸리는데.. 아마 오프라인 수업중에 풀었던 문제를 한번 쭉 풀어본 뒤 다시 처음부터 쭉 풀어볼 예정이니, 다시 돌아올 때는 좀더 깔끔하게 풀 수 있는 실력이 되어있으면 좋을 것 같다.

먼저 일하는 날과 얻을 수 있는 수익을 배열로 만들어 저장해 두고 DPS 로 문제를 풀었다. 풀고나서 구글링 해보니 DP 로도 풀 수 있는 문제인 것 같은데, 좀 더 고민하고 후에 다시 도전해봐야겠다.

코드

package baekjoon.algorithm.day02;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.Queue;
import java.util.Set;
import java.util.StringTokenizer;

public class CrushWallAndMove4 {


	static int[][] baseMap;
	static int[][] answerMap;
	static boolean[][] groupMap;
	static ArrayList<Integer> arrGroupCnt = new ArrayList<>();
	static char groupNum = 2;
	static final int[][] DIR = { { 0, 1 }, { 0, -1 }, { -1, 0 }, { 1, 0 } };

	static int N, M;

	public static void main(String[] args) throws IOException {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		StringTokenizer stk = new StringTokenizer(br.readLine());
		N = Integer.parseInt(stk.nextToken());
		M = Integer.parseInt(stk.nextToken());
		baseMap = new int[N][M];
		answerMap = new int[N][M];
		groupMap = new boolean[N][M];
		for (int i = 0; i < N; i++) {
			String line = br.readLine();
			for (int j = 0; j < line.length(); j++) {
				int num = Character.getNumericValue(line.charAt(j));
				baseMap[i][j] = num;
				answerMap[i][j] = num;
			}
		}
		makeGroup();
		crushWall();
		StringBuilder stb = new StringBuilder();
		for (int i = 0; i < N; i++) {
			for (int j = 0; j < M; j++) {
				stb.append(answerMap[i][j]);
			}
			stb.append("\n");
		}

		System.out.println(stb.toString());
	}

	private static void makeGroup() {
		for (int i = 0; i < N; i++) {
			for (int j = 0; j < M; j++) {
				if (baseMap[i][j] == 0) {
					// 그룹화 시키기
					int groupCnt = 0;
					Queue<Integer> que = new LinkedList<Integer>();
					groupMap[i][j] = true;
					baseMap[i][j] = groupNum;
					que.add(i);
					que.add(j);
					while (!que.isEmpty()) {
						int x = que.poll();
						int y = que.poll();
						groupCnt++;
						for (int k = 0; k < 4; k++) {
							int tX = x + DIR[k][0];
							int tY = y + DIR[k][1];
							if (tX >= 0 && tX < N && tY >= 0 && tY < M) {
								if (baseMap[tX][tY] == 0 && !groupMap[tX][tY]) {
									groupMap[tX][tY] = true;
									baseMap[tX][tY] = groupNum;
									que.add(tX);
									que.add(tY);
								} else {
									continue;
								}
							}
						}
					}
					arrGroupCnt.add(groupCnt);
					groupNum++;
				}
			}
		}
	}

	private static void crushWall() {
		for (int i = 0; i < N; i++) {
			for (int j = 0; j < M; j++) {
				if (baseMap[i][j] == 1) {
					Set<Integer> temp = new HashSet<Integer>();
					for (int k = 0; k < 4; k++) {
						int tX = i + DIR[k][0];
						int tY = j + DIR[k][1];
						if (tX >= 0 && tX < N && tY >= 0 && tY < M && baseMap[tX][tY] != 1) {
							temp.add(baseMap[tX][tY] - 2);
						}
					}
					int sum = 1;
					for (Integer integer : temp) {
						sum += arrGroupCnt.get(integer);
					}
					answerMap[i][j] = sum % 10;
				}

			}
		}
	}

}

기억에 남길 것!

  • 문제를 시작전에 과연 내 풀이가 시간 복잡도를 계산하고 시작하자.
  • 문제를 잘 읽고 자료구조를 어떻게 만들지 신중하게 생각해서 만들고 시작해야 후에 험한꼴을 보지 않는다..
© 2020 JunhoBaik, Built with Gatsby