벽돌 깨기


Software Expert Academy [5656] 벽돌 깨기

문제보기
Alt text

소스코드

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

public class Solution {
	public static void main(String[] args) throws NumberFormatException, IOException {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		StringTokenizer st;
		int T = Integer.parseInt(br.readLine());

		for (int tc = 1; tc <= T; tc++) {
			st = new StringTokenizer(br.readLine(), " ");
			N = Integer.parseInt(st.nextToken());// 구슬의 개수
			W = Integer.parseInt(st.nextToken()); // 가로
			H = Integer.parseInt(st.nextToken()); // 세로

			map = new int[H][W];

			for (int i = 0; i < H; i++) {
				st = new StringTokenizer(br.readLine(), " ");
				for (int j = 0; j < W; j++) {
					map[i][j] = Integer.parseInt(st.nextToken());
				}
			}
			min = 987654321;
			function(0);
			System.out.println("#" + tc + " " + min);
		}
	}

	static int[][] map;
	static int N, W, H;
	static int min;

	static void function(int ball) {
		if (ball == N) {
			int sum = 0;
			for (int i = 0; i < H; i++) {
				for (int j = 0; j < W; j++) {
					if (map[i][j] != 0)
						sum++;
				}
			}
			min = Math.min(min, sum);
			return;
		}

		int cnt = 0; // 구슬이 N개가 되기전에 벽돌이 다 깨지는지 확인하기 위해
		for (int i = 0; i < W; i++) {
			for (int j = 0; j < H; j++) {
				cnt++;

				if (map[j][i] != 0) {
					int[][] copyMap = copyMap();
					int len = map[j][i];
					boom(j, i, len);

					// 벽돌들 내리기
					downWall();
					function(ball + 1);
					map = copyMap;
					cnt = 0;
					break;
				}
			}
		}
		if (cnt == H * W)
			min = 0;
	}

	static void boom(int i, int j, int len) { // 처음 i,j는 구슬이 맞은 위치

		for (int k = 0; k < len; k++) { // 자기 자신도 처리하기위해 -1안하겠음
			// 상
			if (i - k >= 0) {
				if (i - k != i && map[i - k][j] != 0) {
					int length = map[i - k][j];
					boom(i - k, j, length);
				}
				map[i - k][j] = 0;
			}
			// 하
			if (i + k < H) {
				if (i + k != i && map[i + k][j] != 0) {
					int length = map[i + k][j];
					boom(i + k, j, length);
				}
				map[i + k][j] = 0;
			}
			// 좌
			if (j - k >= 0) {
				if (j - k != j && map[i][j - k] != 0) {
					int length = map[i][j - k];
					boom(i, j - k, length);
				}
				map[i][j - k] = 0;
			}
			// 우
			if (j + k < W) {
				if (j + k != j && map[i][j + k] != 0) {
					int length = map[i][j + k];
					boom(i, j + k, length);
				}
				map[i][j + k] = 0;
			}
		}

	}

	public static int[][] copyMap() {
		int[][] newMap = new int[H][W];
		for (int i = 0; i < H; i++) {
			newMap[i] = map[i].clone();
		}
		return newMap;
	}

	public static void downWall() {
		int[][] downMap = new int[H][W];
		for (int j = 0; j < W; j++) {
			int idx = H - 1;
			for (int i = H - 1; i >= 0; i--) {
				if (map[i][j] != 0) {
					downMap[idx--][j] = map[i][j];
				}
			}
		}
		map = downMap;
	}
}