Skip to content

Commit 8133ba6

Browse files
authored
Merge pull request #72 from chaesc1/chaesc1
[BOJ] 미네랄 / 골드1 / 80분 "https://www.acmicpc.net/problem/2933"
2 parents cac0a62 + 094edd8 commit 8133ba6

File tree

1 file changed

+161
-0
lines changed

1 file changed

+161
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,161 @@
1+
package week7.Day0904.BOJ미네랄;
2+
3+
import java.io.BufferedReader;
4+
import java.io.InputStreamReader;
5+
import java.util.ArrayList;
6+
import java.util.Stack;
7+
import java.util.StringTokenizer;
8+
9+
/*
10+
1.입력받기:
11+
R, C: 맵의 행과 열 크기.
12+
맵의 상태: 미네랄('x')과 빈공간('.')으로 구성.
13+
막대를 던지는 높이를 저장하는 리스트.
14+
15+
2.막대 던지기:
16+
왼쪽에서 오른쪽으로, 오른쪽에서 왼쪽으로 번갈아가며 막대를 던지며 미네랄을 파괴.
17+
18+
3.클러스터 확인 및 떨어뜨리기:
19+
파괴된 미네랄을 기준으로 나눠진 클러스터가 공중에 떠 있는지 확인.
20+
공중에 떠 있다면 클러스터를 내려놓음.
21+
*/
22+
public class BOJ2933 {
23+
static int R, C;
24+
static char[][] map;
25+
static int[] dx = {-1, 1, 0, 0};
26+
static int[] dy = {0, 0, -1, 1};
27+
static ArrayList<Integer> shoot;
28+
29+
public static void main(String[] args) throws Exception {
30+
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
31+
StringTokenizer st = new StringTokenizer(br.readLine());
32+
33+
R = Integer.parseInt(st.nextToken());
34+
C = Integer.parseInt(st.nextToken());
35+
map = new char[R][C];
36+
37+
for (int i = 0; i < R; i++) {
38+
String line = br.readLine();
39+
for (int j = 0; j < C; j++) {
40+
map[i][j] = line.charAt(j);
41+
}
42+
}
43+
44+
int count = Integer.parseInt(br.readLine());
45+
shoot = new ArrayList<>();
46+
47+
st = new StringTokenizer(br.readLine());
48+
for (int i = 0; i < count; i++) {
49+
shoot.add(Integer.parseInt(st.nextToken()));
50+
}
51+
52+
// 막대 던지기
53+
for (int i = 0; i < shoot.size(); i++) {
54+
int height = R - shoot.get(i); // 높이는 아래에서 올라오는 구조 R - Height
55+
if (i % 2 == 0) {
56+
// 왼쪽에서 던지기
57+
for (int j = 0; j < C; j++) {
58+
if (map[height][j] == 'x') {
59+
map[height][j] = '.'; // 미네랄 파괴
60+
break;
61+
}
62+
}
63+
} else {
64+
// 오른쪽에서 던지기
65+
for (int j = C - 1; j >= 0; j--) {
66+
if (map[height][j] == 'x') {
67+
map[height][j] = '.';
68+
break;
69+
}
70+
}
71+
}
72+
// 클러스터 떨어트리기
73+
dropCluster();
74+
}
75+
76+
// 최종 맵 출력
77+
printMap();
78+
}
79+
80+
// 맵 출력하는 함수
81+
private static void printMap() {
82+
for (int i = 0; i < R; i++) {
83+
for (int j = 0; j < C; j++) {
84+
System.out.print(map[i][j]);
85+
}
86+
System.out.println();
87+
}
88+
}
89+
90+
// 네 방향 중 하나로 인접한 미네랄이 포함된 두 칸은 같은 클러스터
91+
private static void dropCluster() {
92+
boolean[][] isVisited = new boolean[R][C];
93+
ArrayList<int[]> floatingCluster = new ArrayList<>(); // 떠있는 클러스터
94+
95+
// 바닥과 연결되어 붙어있는 클러스트는 방문표시
96+
for (int i = 0; i < C; i++) {
97+
if (map[R - 1][i] == 'x' && !isVisited[R - 1][i]) {
98+
isVisited[R - 1][i] = true;
99+
dfs(R - 1, i, isVisited);
100+
}
101+
}
102+
103+
// 공중에 떠있는 클러스터 탐색
104+
for (int i = 0; i < R; i++) {
105+
for (int j = 0; j < C; j++) {
106+
if (map[i][j] == 'x' && !isVisited[i][j]) {
107+
floatingCluster.add(new int[]{i, j});
108+
map[i][j] = '.';
109+
}
110+
}
111+
}
112+
113+
if (floatingCluster.isEmpty()) {
114+
return;
115+
}
116+
117+
// 공중에 떠있는 클러스터를 아래로 떨어트리기
118+
boolean drop = true;
119+
while (drop) {
120+
for (int[] cluster : floatingCluster) {
121+
int nx = cluster[1];
122+
int ny = cluster[0] + 1;
123+
if (ny >= R || (map[ny][nx] == 'x' && isVisited[ny][nx])) {
124+
drop = false;
125+
break;
126+
}
127+
}
128+
129+
if (drop) {
130+
for (int i = 0; i < floatingCluster.size(); i++) {
131+
floatingCluster.get(i)[0]++;
132+
}
133+
}
134+
}
135+
// 새로운 위치에 다시 놓아
136+
for (int[] cluster : floatingCluster) {
137+
map[cluster[0]][cluster[1]] = 'x';
138+
}
139+
}
140+
141+
private static void dfs(int x, int y, boolean[][] isVisited) {
142+
Stack<int[]> stack = new Stack<>();
143+
stack.push(new int[]{x, y});
144+
isVisited[x][y] = true;
145+
146+
while (!stack.isEmpty()) {
147+
int[] now = stack.pop();
148+
for (int i = 0; i < 4; i++) {
149+
int nx = now[0] + dx[i];
150+
int ny = now[1] + dy[i];
151+
if (nx < 0 || nx >= R || ny < 0 || ny >= C || isVisited[nx][ny] || map[nx][ny] == '.') {
152+
continue;
153+
}
154+
155+
stack.push(new int[]{nx, ny});
156+
isVisited[nx][ny] = true;
157+
}
158+
}
159+
}
160+
161+
}

0 commit comments

Comments
 (0)