Skip to content

Commit 336fe73

Browse files
committed
[Gold I] Title: 청소년 상어, Time: 100 ms, Memory: 14332 KB -BaekjoonHub
1 parent 2c1152e commit 336fe73

2 files changed

Lines changed: 233 additions & 0 deletions

File tree

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
# [Gold I] 청소년 상어 - 19236
2+
3+
[문제 링크](https://www.acmicpc.net/problem/19236)
4+
5+
### 성능 요약
6+
7+
메모리: 14332 KB, 시간: 100 ms
8+
9+
### 분류
10+
11+
구현, 시뮬레이션, 백트래킹
12+
13+
### 제출 일자
14+
15+
2025년 11월 24일 16:20:57
16+
17+
### 문제 설명
18+
19+
<p><a href="/problem/16236">아기 상어</a>가 성장해 청소년 상어가 되었다.</p>
20+
21+
<p>4×4크기의 공간이 있고, 크기가 1×1인 정사각형 칸으로 나누어져 있다. 공간의 각 칸은 (x, y)와 같이 표현하며, x는 행의 번호, y는 열의 번호이다. 한 칸에는 물고기가 한 마리 존재한다. 각 물고기는 번호와 방향을 가지고 있다. 번호는 1보다 크거나 같고, 16보다 작거나 같은 자연수이며, 두 물고기가 같은 번호를 갖는 경우는 없다. 방향은 8가지 방향(상하좌우, 대각선) 중 하나이다.</p>
22+
23+
<p>오늘은 청소년 상어가 이 공간에 들어가 물고기를 먹으려고 한다. 청소년 상어는 (0, 0)에 있는 물고기를 먹고, (0, 0)에 들어가게 된다. 상어의 방향은 (0, 0)에 있던 물고기의 방향과 같다. 이후 물고기가 이동한다.</p>
24+
25+
<p>물고기는 번호가 작은 물고기부터 순서대로 이동한다. 물고기는 한 칸을 이동할 수 있고, 이동할 수 있는 칸은 빈 칸과 다른 물고기가 있는 칸, 이동할 수 없는 칸은 상어가 있거나, 공간의 경계를 넘는 칸이다. 각 물고기는 방향이 이동할 수 있는 칸을 향할 때까지 방향을 45도 반시계 회전시킨다. 만약, 이동할 수 있는 칸이 없으면 이동을 하지 않는다. 그 외의 경우에는 그 칸으로 이동을 한다. 물고기가 다른 물고기가 있는 칸으로 이동할 때는 서로의 위치를 바꾸는 방식으로 이동한다.</p>
26+
27+
<p>물고기의 이동이 모두 끝나면 상어가 이동한다. 상어는 방향에 있는 칸으로 이동할 수 있는데, 한 번에 여러 개의 칸을 이동할 수 있다. 상어가 물고기가 있는 칸으로 이동했다면, 그 칸에 있는 물고기를 먹고, 그 물고기의 방향을 가지게 된다. 이동하는 중에 지나가는 칸에 있는 물고기는 먹지 않는다. 물고기가 없는 칸으로는 이동할 수 없다. 상어가 이동할 수 있는 칸이 없으면 공간에서 벗어나 집으로 간다. 상어가 이동한 후에는 다시 물고기가 이동하며, 이후 이 과정이 계속해서 반복된다.</p>
28+
29+
<p style="text-align: center;"><img alt="" src="" style="width: 333px; height: 338px;"></p>
30+
31+
<p style="text-align: center;"><그림 1></p>
32+
33+
<p><그림 1>은 청소년 상어가 공간에 들어가기 전 초기 상태이다. 상어가 공간에 들어가면 (0, 0)에 있는 7번 물고기를 먹고, 상어의 방향은 ↘이 된다. <그림 2>는 상어가 들어간 직후의 상태를 나타낸다.</p>
34+
35+
<p style="text-align: center;"><img alt="" src="" style="width: 328px; height: 332px;"></p>
36+
37+
<p style="text-align: center;"><그림 2></p>
38+
39+
<p>이제 물고기가 이동해야 한다. 1번 물고기의 방향은 ↗이다. ↗ 방향에는 칸이 있고, 15번 물고기가 들어있다. 물고기가 있는 칸으로 이동할 때는 그 칸에 있는 물고기와 위치를 서로 바꿔야 한다. 따라서, 1번 물고기가 이동을 마치면 <그림 3>과 같아진다.</p>
40+
41+
<p style="text-align: center;"><img alt="" src="" style="width: 326px; height: 331px;"></p>
42+
43+
<p style="text-align: center;"><그림 3></p>
44+
45+
<p>2번 물고기의 방향은 ←인데, 그 방향에는 상어가 있으니 이동할 수 없다. 방향을 45도 반시계 회전을 하면 ↙가 되고, 이 칸에는 3번 물고기가 있다. 물고기가 있는 칸이니 서로 위치를 바꾸고, <그림 4>와 같아지게 된다.</p>
46+
47+
<p style="text-align: center;"><img alt="" src="" style="width: 327px; height: 329px;"></p>
48+
49+
<p style="text-align: center;"><그림 4></p>
50+
51+
<p>3번 물고기의 방향은 ↑이고, 존재하지 않는 칸이다. 45도 반시계 회전을 한 방향 ↖도 존재하지 않으니, 다시 회전을 한다. ← 방향에는 상어가 있으니 또 회전을 해야 한다. ↙ 방향에는 2번 물고기가 있으니 서로의 위치를 교환하면 된다. 이런 식으로 모든 물고기가 이동하면 <그림 5>와 같아진다.</p>
52+
53+
<p style="text-align: center;"><img alt="" src="" style="width: 330px; height: 329px;"></p>
54+
55+
<p style="text-align: center;"><그림 5></p>
56+
57+
<p>물고기가 모두 이동했으니 이제 상어가 이동할 순서이다. 상어의 방향은 ↘이고, 이동할 수 있는 칸은 12번 물고기가 있는 칸, 15번 물고기가 있는 칸, 8번 물고기가 있는 칸 중에 하나이다. 만약, 8번 물고기가 있는 칸으로 이동하면, <그림 6>과 같아지게 된다.</p>
58+
59+
<p style="text-align: center;"><img alt="" src="" style="width: 326px; height: 328px;"></p>
60+
61+
<p style="text-align: center;"><그림 6></p>
62+
63+
<p>상어가 먹을 수 있는 물고기 번호의 합의 최댓값을 구해보자.</p>
64+
65+
### 입력
66+
67+
<p>첫째 줄부터 4개의 줄에 각 칸의 들어있는 물고기의 정보가 1번 행부터 순서대로 주어진다. 물고기의 정보는 두 정수 a<sub>i</sub>, b<sub>i</sub>로 이루어져 있고, a<sub>i</sub>는 물고기의 번호, b<sub>i</sub>는 방향을 의미한다. 방향 b<sub>i</sub>는 8보다 작거나 같은 자연수를 의미하고, 1부터 순서대로 ↑, ↖, ←, ↙, ↓, ↘, →, ↗ 를 의미한다.</p>
68+
69+
### 출력
70+
71+
<p>상어가 먹을 수 있는 물고기 번호의 합의 최댓값을 출력한다.</p>
72+
Lines changed: 161 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,161 @@
1+
import java.util.*;
2+
import java.io.*;
3+
4+
public class Main {
5+
6+
static class Cell {
7+
public Cell(int id, int d) {
8+
this.id = id;
9+
this.dir = d;
10+
}
11+
int id; //0 - 상어
12+
int dir; //북, 북서, 서, ... 반시계 45도
13+
}
14+
15+
static class Pair {
16+
public Pair(int y, int x) {
17+
this.y = y;
18+
this.x = x;
19+
}
20+
int y;
21+
int x;
22+
}
23+
24+
static Cell[][] B;
25+
static Map<Integer, Pair> P;
26+
static int[] Dy = { -1, -1, 0, 1, 1, 1, 0, -1 };
27+
static int[] Dx = { 0, -1, -1, -1, 0, 1, 1, 1 };
28+
static String[] dirs = { "↑", "↖", "←", "↙", "↓", "↘", "→", "↗"};
29+
30+
static int ans;
31+
32+
public static void main(String[] args) throws Exception {
33+
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
34+
B = new Cell[4][4];
35+
P = new HashMap<>();
36+
37+
StringTokenizer st;
38+
for(int i=0;i<4;i++) {
39+
st = new StringTokenizer(br.readLine());
40+
for(int j=0;j<4;j++) {
41+
int a = Integer.parseInt(st.nextToken());
42+
int b = Integer.parseInt(st.nextToken());
43+
B[i][j] = new Cell(a, b-1);
44+
P.put(a, new Pair(i, j));
45+
}
46+
}
47+
48+
ans = 0;
49+
50+
int sum = B[0][0].id;
51+
P.remove(B[0][0].id);
52+
P.put(0, new Pair(0, 0));
53+
B[0][0].id = 0;
54+
55+
dfs(B, P, sum);
56+
57+
System.out.println(ans);
58+
}
59+
60+
private static void dfs(Cell[][] board, Map<Integer, Pair> pos, int sum) {
61+
// System.out.println("dfs " + sum);
62+
63+
printBoard(board);
64+
for(int i=1;i<=16;i++) {
65+
Pair p = pos.get(i);
66+
if(p == null)
67+
continue;
68+
69+
int y = p.y;
70+
int x = p.x;
71+
int d = board[y][x].dir;
72+
73+
for(int j=0;j<8;j++) {
74+
int ny = y + Dy[(d+j)%8];
75+
int nx = x + Dx[(d+j)%8];
76+
if(ny < 0 || nx < 0 || ny >= 4 || nx >= 4)
77+
continue;
78+
if(board[ny][nx] != null && board[ny][nx].id == 0)
79+
continue;
80+
81+
pos.put(board[y][x].id, new Pair(ny, nx));
82+
Cell t = board[ny][nx];
83+
if(t != null)
84+
pos.put(t.id, new Pair(y, x));
85+
86+
board[y][x].dir = (d+j)%8;
87+
88+
board[ny][nx] = board[y][x];
89+
board[y][x] = t;
90+
91+
break;
92+
}
93+
94+
}
95+
96+
printBoard(board);
97+
98+
Pair s = pos.get(0);
99+
int sy = s.y;
100+
int sx = s.x;
101+
int sd = board[sy][sx].dir;
102+
103+
int sny = sy;
104+
int snx = sx;
105+
106+
boolean isEnd = true;
107+
108+
while(true) {
109+
sny += Dy[sd];
110+
snx += Dx[sd];
111+
112+
if(sny < 0 || snx < 0 || sny >= 4 || snx >= 4)
113+
break;
114+
if(board[sny][snx] == null)
115+
continue;
116+
117+
isEnd = false;
118+
119+
//copy state
120+
Cell[][] newBoard = new Cell[4][4];
121+
for(int i=0;i<4;i++) {
122+
for (int j = 0; j < 4; j++) {
123+
if(board[i][j] != null)
124+
newBoard[i][j] = new Cell(board[i][j].id, board[i][j].dir);
125+
else
126+
newBoard[i][j] = null;
127+
}
128+
}
129+
Map<Integer, Pair> newPos = new HashMap<>();
130+
for(Map.Entry<Integer, Pair> e : pos.entrySet())
131+
newPos.put(e.getKey(), new Pair(e.getValue().y, e.getValue().x));
132+
133+
//eat
134+
int tid = board[sny][snx].id;
135+
int newSum = sum + tid;
136+
newPos.remove(tid);
137+
138+
//change
139+
newPos.put(0, new Pair(sny, snx));
140+
newBoard[sny][snx].id = 0;
141+
newBoard[sy][sx] = null;
142+
143+
dfs(newBoard, newPos, newSum);
144+
}
145+
if(isEnd)
146+
ans = Math.max(ans, sum);
147+
}
148+
149+
private static void printBoard(Cell[][] board) {
150+
// for(int i=0;i<4;i++) {
151+
// for(int j=0;j<4;j++) {
152+
// if(board[i][j] == null)
153+
// System.out.print(" ".repeat(4));
154+
// else
155+
// System.out.print(board[i][j].id + "/" + dirs[board[i][j].dir] + " ");
156+
// }
157+
// System.out.println();
158+
// }
159+
// System.out.println();
160+
}
161+
}

0 commit comments

Comments
 (0)