Skip to content

Commit 6839115

Browse files
committed
고다혜: [CT] 고대 문명 유적 탐사_250214
1 parent f0e0bea commit 6839115

File tree

1 file changed

+235
-0
lines changed

1 file changed

+235
-0
lines changed
Lines changed: 235 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,235 @@
1+
import java.io.*;
2+
import java.util.*;
3+
4+
/*
5+
* 고대 문명 유적 탐사
6+
* step1에서 r과 c의 좌표를 for(int r = 1; r < 3; r++) 이렇게 해서 틀렸음
7+
*/
8+
9+
public class DH_고대_문명_유적_탐사 {
10+
static final int SIZE = 5, ROTATE_SIZE = 3;
11+
static int K, M;
12+
static int[][] map; // 유적지 정보
13+
static int[] arr; // 조각 정보
14+
static int result, IDX; // result: 각 턴마다 획득한 유물 가치의 총 합, IDX: 조각 정보의 인덱스
15+
16+
public static void main(String[] args) throws Exception {
17+
initInput();
18+
solution();
19+
}
20+
21+
static void solution() {
22+
23+
StringBuilder sb = new StringBuilder();
24+
25+
while(K-- > 0) {
26+
27+
result = 0;
28+
29+
// 탐사 진행 (1차 유물 획득을 최대로 할 수 있게)
30+
int[][] currentMap = step1();
31+
32+
// 1차 유물 획득 이후 빈 공간 채워주기
33+
currentMap = fillMap(currentMap);
34+
35+
// 회전을 안했다(획득한 가치가 0)면 탐사 종료
36+
if(result == 0) break;
37+
38+
int value = 0;
39+
40+
// 유물 연쇄 획득
41+
// 3개 이상 연결된거 찾아주고, 유적지 채워주기
42+
while((value = getValue(currentMap)) != 0) {
43+
currentMap = fillMap(currentMap);
44+
result += value;
45+
}
46+
47+
// 각 턴마다 afterStep1이라는 배열을 사용하고 있으므로 최종적으로 map배열을 currentMap으로 바꿔줌
48+
map = currentMap;
49+
50+
sb.append(result).append(" ");
51+
}
52+
System.out.println(sb);
53+
}
54+
55+
static int[][] fillMap(int[][] map) {
56+
57+
for(int c = 0; c < SIZE; c++) {
58+
for(int r = SIZE - 1; r >= 0; r--) {
59+
if(map[r][c] != 0) continue;
60+
61+
map[r][c] = arr[IDX];
62+
IDX = (IDX + 1) % M;
63+
}
64+
}
65+
return map;
66+
}
67+
68+
static int[][] step1() {
69+
// (1) 유물 1차 획득 가치를 최대화하고
70+
// (2) 회전 각도가 가장 작은 방법
71+
// (3) 열이 가장 작으면서, (4) 행이 가장 작도록
72+
int maxValue = Integer.MIN_VALUE;
73+
74+
int[][] resultMap = new int[SIZE][SIZE];
75+
76+
for(int t = 0; t < 3; t++) { // (2) 회전한 각도가 가장 작은
77+
for(int c = 1; c < 4; c++) { // (3) 중심 좌표의 열이 가장 작은
78+
for(int r = 1; r < 4; r++) { // (4) 행이 가장 작은
79+
int[][] tmp = rotate(r, c, t);
80+
81+
int value = getValue(tmp);
82+
83+
if(maxValue < value) { // (1) 유물 1차 획득 가치를 최대화
84+
maxValue = value;
85+
resultMap = tmp;
86+
}
87+
}
88+
}
89+
}
90+
91+
result += maxValue; // 최대 유물 가치 더해주기
92+
93+
return resultMap;
94+
}
95+
96+
static void print(int[][] arr) {
97+
System.out.println("map 출력 ----------");
98+
for(int r = 0; r < arr.length; r++) {
99+
System.out.println(Arrays.toString(arr[r]));
100+
}
101+
}
102+
103+
static int[][] rotate(int r, int c, int t) {
104+
int[][] rotateMap = new int[SIZE][SIZE];
105+
106+
// 배열 복사
107+
for(int cr = 0; cr < SIZE; cr++) rotateMap[cr] = Arrays.copyOf(map[cr], SIZE);
108+
109+
// 회전 기준점을 (1, 1)로 놓고 회전 진행
110+
for(int tr = -1; tr < 2; tr++) {
111+
for(int tc = -1; tc < 2; tc++) {
112+
int cr = r + tr, cc = c + tc;
113+
114+
int tmp = map[cr][cc];
115+
116+
int sr = r - 1, sc = c - 1;
117+
118+
int tmpR = r + tr - sr, tmpC = c + tc - sc;
119+
int nr = 0, nc = 0;
120+
121+
// (r, c)를 기준으로 90도 회전
122+
if(t == 0) {
123+
nr = tmpC;
124+
nc = (ROTATE_SIZE - 1) - tmpR;
125+
}
126+
127+
// (r, c)를 기준으로 180도 회전
128+
if(t == 1) {
129+
nr = ROTATE_SIZE - 1 - tmpR;
130+
nc = ROTATE_SIZE - 1 - tmpC;
131+
}
132+
133+
// (r, c)를 기준으로 270도 회전
134+
if(t == 2) {
135+
nr = ROTATE_SIZE - 1 - tmpC;
136+
nc = tmpR;
137+
}
138+
139+
rotateMap[nr + sr][nc + sc] = tmp;
140+
}
141+
}
142+
143+
return rotateMap;
144+
}
145+
146+
static int[] dr = {-1, 1, 0, 0}, dc = {0, 0, -1, 1};
147+
148+
// bfs를 하면서 3개 이상 연속으로 있는 그룹 찾아주기
149+
static int getValue(int[][] tmp) {
150+
151+
int value = 0;
152+
boolean[][] v = new boolean[SIZE][SIZE];
153+
154+
for(int r = 0; r < SIZE; r++) {
155+
for(int c = 0; c < SIZE; c++) {
156+
if(v[r][c]) continue;
157+
158+
Queue<Integer> q = new ArrayDeque<Integer>(); // bfs 탐색을 위한 큐
159+
Queue<Integer> removeQ = new ArrayDeque<Integer>(); // 그룹이 생성된 후, 없앨 위치를 저장하기 위한 큐
160+
161+
v[r][c] = true;
162+
163+
int currentValue = 1;
164+
int pos = r * SIZE + c;
165+
166+
q.add(pos);
167+
removeQ.add(pos);
168+
169+
while(!q.isEmpty()) {
170+
int currentPos = q.poll();
171+
int cr = currentPos / SIZE, cc = currentPos % SIZE;
172+
173+
for(int d = 0; d < 4; d++) {
174+
int nr = cr + dr[d];
175+
int nc = cc + dc[d];
176+
177+
if(!check(nr, nc) || v[nr][nc] || tmp[nr][nc] != tmp[r][c]) continue;
178+
179+
int nextPos = nr * SIZE + nc;
180+
q.add(nextPos);
181+
removeQ.add(nextPos);
182+
v[nr][nc] = true;
183+
currentValue += 1;
184+
}
185+
}
186+
187+
if(currentValue < 3) continue;
188+
189+
value += currentValue;
190+
191+
while(!removeQ.isEmpty()) {
192+
int removePos = removeQ.poll();
193+
int rr = removePos / SIZE;
194+
int rc = removePos % SIZE;
195+
196+
tmp[rr][rc] = 0;
197+
}
198+
}
199+
}
200+
201+
return value;
202+
}
203+
204+
static boolean check(int r, int c) {
205+
return r >= 0 && r < SIZE && c >= 0 && c < SIZE;
206+
}
207+
208+
static void initInput() throws Exception {
209+
210+
System.setIn(new FileInputStream("./input/고대문명유적탐사.txt"));
211+
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
212+
StringTokenizer st = new StringTokenizer(br.readLine());
213+
214+
K = Integer.parseInt(st.nextToken()); // 탐사 반복 횟수
215+
M = Integer.parseInt(st.nextToken()); // 유물 조각의 개수
216+
217+
arr = new int[M];
218+
219+
map = new int[SIZE][SIZE];
220+
221+
// 유적지 정보
222+
for(int r = 0; r < map.length; r++) {
223+
st = new StringTokenizer(br.readLine());
224+
225+
for(int c = 0; c < map[0].length; c++) {
226+
map[r][c] = Integer.parseInt(st.nextToken());
227+
}
228+
}
229+
230+
st = new StringTokenizer(br.readLine());
231+
232+
// 유적 벽면에 써 있는 숫자
233+
for(int i = 0; i < arr.length; i++) arr[i] = Integer.parseInt(st.nextToken());
234+
}
235+
}

0 commit comments

Comments
 (0)