[SWEA] 5656 벽돌깨기
라인 코테 통과했다~~ 토요일에 필기 시험 보러간다 ㅠㅠ
늦은감이 매우 크지만 오늘부터 정처기라도 봐야겠다(…)
오늘의 문풀은 딱 여기까지만! 집에가서 책 읽어봐야지 @_@
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.LinkedList;
import java.util.Queue;
import java.util.Stack;
import java.util.StringTokenizer;
// 좌표를 저장할 클래스 - BFS에서 사용
class Pair{
int x;
int y;
Pair(int x, int y){
this.x = x;
this.y = y;
}
}
public class Main {
static int n;
static int w;
static int h;
static int remain;
static int[] dx = {1, -1, 0, 0};
static int[] dy = {0, 0, 1, -1};
static int bfs(int[][] map, int i, int j) {
Queue<Pair> q = new LinkedList<Pair>();
q.add(new Pair(i, j));
while(!q.isEmpty()) {
Pair p = q.remove();
int x = p.x;
int y = p.y;
int num = map[x][y]; // 미리 값을 빼주고
map[x][y] = 0; // 0으로 처리해줘야 중복으로 안부순다
// 벽돌에 적힌 숫자만큼 상하좌우 다 뿌순다
for(int l = 1 ; l < num ; l++ ) {
for(int k = 0 ; k < 4 ; k++) {
int nx = x + dx[k]*l;
int ny = y + dy[k]*l;
if(nx>=0 && nx < h && ny >= 0 && ny< w) {
if(map[nx][ny] != 0) {
q.add(new Pair(nx,ny));
}
}
}
}
}
// 건재한 블럭의 갯수 세기
int bricks = 0;
for(int ii = 0 ; ii < h ; ii++) {
for(int jj = 0 ; jj < w ; jj++) {
if(map[ii][jj] != 0) {
bricks++;
}
}
}
return bricks; // 반환해준다
}
static void go(int[][] map, int cnt, int brick) {
// 종료 조건 1 - 모든 횟수를 소진 했을 때
if(cnt >= n) {
if(remain > brick) {
remain = brick; // 최소 남은 블럭 갯수 갱신
}
return;
}
// 종료 조건 2 - 더이상 깰 블럭이 없을때를 위한 변수
boolean allBroken = true;
for(int j = 0 ; j < w ; j++) {
for(int i = 0 ; i < h ; i++) {
if(map[i][j] != 0) {
allBroken = false; // 아직 깰게 남았다
int num = map[i][j]; // 적힌 숫자가
if(num == 1) { // 1일때는 걔만 뿌시면 된다
map[i][j] = 0;
go(map, cnt+1, brick-1);
map[i][j] = num; // 원상복구 해주자
}else { // 적힌 숫자가 1보다 크다면
int[][] map2 = new int[h][w]; // 원상복구할 엄두가 안나므로 미리 복사해서 쓰자
for(int row = 0 ; row < h ; row++) {
System.arraycopy(map[row], 0, map2[row], 0, w);
}
// bfs를 통해 뿌셔뿌셔 해주자
int bricks = bfs(map2, i, j);
// arrange map - 곳곳에 빈 0이 있다면 중력 처리 해주자
for(int col = 0 ; col < w ; col++) {
// 이럴땐 스택쓰면 참 편하더라~~ 자료구조 배우길 잘했다
Stack<Integer> stack = new Stack<Integer>();
for(int row = 0 ; row < h ; row++) {
if(map2[row][col] != 0) {
stack.push(map2[row][col]);
map2[row][col] = 0;
}
}
int hh = h;
while(!stack.isEmpty()) {
map2[hh-- -1][col] = stack.pop();
}
}
// 재귀호출
go(map2, cnt+1, bricks);
}
break; // 각 컬럼의 맨 상단만 구슬이 닿을 수 있으므로 빠져나옴
}
}
}
// 종료 조건 2 - 더이상 깰 블럭이 없을 때
if(allBroken) {
if(remain > brick) {
remain = brick;
}
return;
}
}
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
int t = Integer.parseInt(br.readLine());
int idx = 1;
StringBuilder sb = new StringBuilder();
while(t-->0) {
StringTokenizer st = new StringTokenizer(br.readLine());
n = Integer.parseInt(st.nextToken());
w = Integer.parseInt(st.nextToken());
h = Integer.parseInt(st.nextToken());
int[][] map = new int[h][w];
remain = 0;
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());
if(map[i][j] != 0) {
remain++; // 부술 수 있는 벽돌의 갯수를 센다
}
}
}
go(map, 0, remain);
sb.append("#" + idx++ + " " + remain + "\n");
}
System.out.println(sb);
}
}
Comments