Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
Tags
- JPA
- 알고리즘기본개념
- 코딩테스트실력진단
- 자바
- JUnit
- 다익스트라
- SSAFY
- 코딩테스트
- 트러블슈팅
- 유니온파인드
- SWEA
- 싸피
- BFS
- Spring
- 백준
- 코테
- 그리디
- 그래프
- 알고리즘
- DFS
- database
- 완탐
- DP
- 기본유형
- 부분수열의합2
- 완전탐색
- 다시보기
- Union Find
- 코드트리
- Java
Archives
- Today
- Total
HwangHub
[Java/시뮬레이션] SWEA. 벽돌깨기 본문
🤔 Intuition
중복 순열을 사용해서 터뜨릴 벽돌을 선택하고, 터뜨리면 되는 문제다. 시뮬레이션 유형이라고 판단했다.
🔎 Algorithm & Complexity
* @algorithm simulation
* @time (W^4 * W * H) -> 211 ms
* @memory (W * H) -> 98,464 kb
👨🏻💻 Logic
관건은, 중복 순열을 일반적인 permutation으로 구하면 시간이 터지므로 효율적으로 뽑아야 한다는 거다.
즉, 순열을 다 뽑아놓고 그것에 대하여 숫자를 계산하는 게 아니라, 각 숫자를 뽑으면서 그 때마다 시뮬레이션을 수행해야 한다.
이 포인트 말고는 특별할 거 없는 시뮬레이션이었다.
public class SWEA_벽돌깨기 {
private static int N, W, H, ans, res, y, x, r, ny, nx;
private static int[][] map;
private static int[] now;
private static int[] dy = {1, -1, 0, 0};
private static int[] dx = {0, 0, 1, -1};
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
StringBuilder sb = new StringBuilder();
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];
ans = (int) 1e9;
for (int i = 0; i < H; i++) {
st = new StringTokenizer(br.readLine());
for (int j = 0; j < W; j++) {
int num = Integer.parseInt(st.nextToken());
map[i][j] = num;
}
}
go(map, 0);
sb.append(String.format("#%d %d\n", tc, ans));
}
br.close();
bw.write(sb.toString());
bw.flush();
bw.close();
}
private static void go(int[][] map, int depth) {
getLeft(map);
if (res == 0 || depth == N) {
ans = Math.min(ans, res);
return;
}
for (int j = 0; j < W; j++) {
int[][] copyMap = copyMap(map);
int sy = -1, sx = j;
for (int i = 0; i < H; i++) {
if (copyMap[i][j] > 0) {
sy = i;
break;
}
}
if (sy == -1) {
continue;
}
// sy, sx 정해진 순간.
int target = copyMap[sy][sx];
bomb(copyMap, sy, sx);
if (target > 1) {
gravity(copyMap);
}
go(copyMap, depth + 1);
}
}
private static void getLeft(int[][] map) {
res = 0;
for (int i = 0; i < H; i++) {
for (int j = 0; j < W; j++) {
if (map[i][j] > 0) {
res++;
}
}
}
}
private static void print(int[][] copyMap) {
System.out.println("-------------");
for (int i = 0; i < H; i++) {
for (int k = 0; k < W; k++) {
System.out.print(copyMap[i][k] + " ");
}
System.out.println();
}
System.out.println("-------------");
}
private static boolean inRange(int y, int x) {
return y >= 0 && y < H && x >= 0 && x < W;
}
private static int[][] copyMap(int[][] map) {
int[][] temp = new int[H][W];
for (int i = 0; i < H; i++) {
temp[i] = map[i].clone();
}
return temp;
}
private static void bomb(int[][] map, int sy, int sx) {
Queue<int[]> q = new ArrayDeque<>();
q.add(new int[]{sy, sx, map[sy][sx] - 1});
map[sy][sx] = -1;
while (!q.isEmpty()) {
now = q.poll();
y = now[0];
x = now[1];
r = now[2]; // range
for (int i = 0; i < 4; i++) {
for (int j = 1; j <= r; j++) {
ny = y + dy[i] * j;
nx = x + dx[i] * j;
if (inRange(ny, nx) && map[ny][nx] > 0) {
if (map[ny][nx] > 1) {
q.add(new int[]{ny, nx, map[ny][nx] - 1});
}
map[ny][nx] = -1;
}
}
}
}
}
private static void gravity(int[][] map) {
for (int j = 0; j < W; j++) {
int[] g = new int[H];
int idx = H-1;
for (int i = H-1; i >= 0; i--) {
if (map[i][j] > 0) {
g[idx--] = map[i][j];
}
}
for (int i = 0; i < H; i++) {
map[i][j] = g[i];
}
}
}
}
'workspace > 알고리즘' 카테고리의 다른 글
[Java/백트래킹] 백준 17136. 색종이 붙이기 (0) | 2024.04.04 |
---|---|
[Java/플로이드워셜] SWEA. 키 순서 (0) | 2024.04.03 |
[Java/시뮬레이션] 백준 17143. 낚시왕 (0) | 2024.04.02 |
[Java/다익스트라] 백준 4485. 녹색 옷 입은 애가 젤다지? (0) | 2024.04.02 |
[Java/수학] SWEA. 원점으로 집합 (1) | 2024.04.02 |
Comments