최's 먹공로그
SEA5656_벽돌깨기 본문
https://www.swexpertacademy.com/main/code/problem/problemDetail.do?contestProbId=AWXRQm6qfL0DFAUo
문제정리
1. 구슬은 N번만 쏠 수 있다 , W = C , H = R 이다
2. 0은 빈 공간 , 그 외의 숫자는 벽돌을 의미한다 1~9
3. 구슬은 좌, 우로만 움직일 수 있어서 항상 맨 위에 있는 벽돌만 깨트릴 수 있다
4. 구슬이 명중한 벽돌의 상하좌우로 (벽돌에 적힌 숫자 - 1)칸 만큼 같이 제거된다
5. 제거되는 범위 내에 있는 벽돌은 동시에 제거된다
6. 빈 공간이 잇을 경우 벽돌은 밑으로 떨어지게 된다
7. N개의 구슬을 떨어트려 최대한 많은 벽돌을 제거하려고 한다
8. 최대한 많은 벽돌을 제거하는 경우일때 남은 벽돌의 개수를 출력
9. 1 <= N <= 4 , 2 <= W <= 12 , 2 <= H <= 15
문제 issue
1. map_clone 사용을 습관화 해야한다
2. 떨어지는 부분 구현에서 q2에 있는 데이터를 밑에서 부터 넣기만 하면 끝난다고 생각했지만 인덱스 map.length - q2_size - 1부터 0까지는
0으로 만들어 줘야한다
3. q에 add할때 0은 넣을 필요 없기 때문에 > 1을 추가 해주니 시간초과를 해결하였다
해결흐름
1. 크기가 N인 배열 생성 , 그 안에 0~W-1 중에서 어디에 떨어트릴 것인가를 설정해준다
2. wHn 중복조합으로 풀면됨 , 조합 한개마다 solve로 가기전에 map_clone에 map을 복사해준다
solve에서는 map_clone만 사용한다
3. 떨어지는 위치에서 처음으로 만나는 벽돌을 q에 담아준다 , 네 방향으로 벽의 크기-1 만큼보면서 크기가 1 이상일 경우만
q에 add해준다 , 동시에 0으로 만들어 준다
4. 떨어지는 부분 -> 열을 고정하고 밑에서 부터 위로 가면서 0이 아닌부분을 q에 담고
다시 밑에서 부터 넣어준다 , map.length - q2_size - 1부터는 원래 있던 데이터이기 때문에 0으로 만들어준다
소스코드
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 | import java.io.BufferedReader; import java.io.InputStreamReader; import java.util.LinkedList; import java.util.Queue; import java.util.StringTokenizer; public class Solution { private static int N; private static int W; private static int H; private static int min; private static int stone_cnt; private static LinkedList<stone> q; private static int[] temp; private static int[] arr; private static int[][] map; private static int[][] map_clone; private static int[] dr = { -1, 0, 1, 0 }; private static int[] dc = { 0, 1, 0, -1 }; static class stone { int r; int c; int number; public stone(int r, int c, int number) { super(); this.r = r; this.c = c; this.number = number; } } public static void main(String[] args) throws Exception { // input BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); int test_case = Integer.parseInt(br.readLine().trim()); for (int t = 1; t <= test_case; t++) { StringTokenizer st = new StringTokenizer(br.readLine().trim(), " "); N = Integer.parseInt(st.nextToken()); W = Integer.parseInt(st.nextToken()); H = Integer.parseInt(st.nextToken()); map = new int[H][W]; map_clone = new int[H][W]; temp = new int[N]; arr = new int[W]; for (int i = 0; i < H; i++) { st = new StringTokenizer(br.readLine().trim(), " "); for (int j = 0; j < W; j++) { map[i][j] = Integer.parseInt(st.nextToken()); } } for (int i = 0; i < W; i++) { arr[i] = i; } // start q = new LinkedList<stone>(); min = Integer.MAX_VALUE; nHr(0, 0); System.out.println("#" + t + " " + min); } // end of test_case } // end of main private static void nHr(int len, int t) { if (len == N) { // temp배열이용 , 벽 깨고 남은 벽 최솟값 갱신 for (int i = 0; i < H; i++) { for (int j = 0; j < W; j++) { map_clone[i][j] = map[i][j]; } } solve(); if (min > stone_cnt) min = stone_cnt; return; } for (int i = 0; i < arr.length; i++) { temp[len] = arr[i]; nHr(len + 1, i); } } private static void solve() { for (int i = 0; i < temp.length; i++) { // 벽돌깨고 int temp_c = temp[i]; for (int rr = 0; rr < H; rr++) { // 가장 위에 있는 벽돌 찾아 if (map_clone[rr][temp_c] != 0) { q.add(new stone(rr, temp_c, map_clone[rr][temp_c])); break; } } while (!q.isEmpty()) { stone s = q.poll(); int r = s.r; int c = s.c; int number = s.number; map_clone[r][c] = 0; for (int j = 0; j < 4; j++) { for (int k = 0; k < number - 1; k++) { int nr = r + dr[j]; int nc = c + dc[j]; if (nr >= 0 && nr < H && nc >= 0 && nc < W) { if(map_clone[nr][nc] > 0) { q.add(new stone(nr, nc, map_clone[nr][nc])); } map_clone[nr][nc] = 0; r = nr; c = nc; } } r = s.r; c = s.c; } } // 아래로 내리고 Queue<Integer> q2 = new LinkedList<>(); for (int j = 0; j < W; j++) { for (int k = H - 1; k >= 0; k--) { if (map_clone[k][j] != 0) { q2.add(map_clone[k][j]); } } int r_idx = H - 1; int q2_size = q2.size(); while (!q2.isEmpty()) { map_clone[r_idx--][j] = q2.poll(); } for (int k = map_clone.length - q2_size-1; k >=0; k--) { map_clone[k][j] = 0; } } } // 남은 벽돌 개수 파악 stone_cnt = 0; for (int i = 0; i < H; i++) { for (int j = 0; j < W; j++) { if (map_clone[i][j] != 0) { stone_cnt++; } } } } // end of solve } // end of class | cs |
'APS' 카테고리의 다른 글
BOJ17406_배열 돌리기4 (0) | 2019.08.15 |
---|---|
SEA5650_[모의 SW 역량테스트] 핀볼 게임 (0) | 2019.08.08 |
SEA5658_보물상자 비밀번호 (2) | 2019.07.15 |
BOJ14888_연산자끼워넣기 (2) | 2019.07.10 |
BOJ14889_스타트와 링크 (0) | 2019.07.06 |