Skip to content

Commit 2edfb2d

Browse files
committed
[Gold V] Title: 상어 초등학교, Time: 164 ms, Memory: 16200 KB -BaekjoonHub
1 parent 6898352 commit 2edfb2d

File tree

2 files changed

+363
-0
lines changed

2 files changed

+363
-0
lines changed
Lines changed: 223 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,223 @@
1+
# [Gold V] 상어 초등학교 - 21608
2+
3+
[문제 링크](https://www.acmicpc.net/problem/21608)
4+
5+
### 성능 요약
6+
7+
메모리: 16200 KB, 시간: 164 ms
8+
9+
### 분류
10+
11+
구현
12+
13+
### 제출 일자
14+
15+
2025년 2월 12일 17:04:09
16+
17+
### 문제 설명
18+
19+
<p>상어 초등학교에는 교실이 하나 있고, 교실은 N×N 크기의 격자로 나타낼 수 있다. 학교에 다니는 학생의 수는 N<sup>2</sup>명이다. 오늘은 모든 학생의 자리를 정하는 날이다. 학생은 1번부터 N<sup>2</sup>번까지 번호가 매겨져 있고, (r, c)는 r행 c열을 의미한다. 교실의 가장 왼쪽 윗 칸은 (1, 1)이고, 가장 오른쪽 아랫 칸은 (N, N)이다.</p>
20+
21+
<p>선생님은 학생의 순서를 정했고, 각 학생이 좋아하는 학생 4명도 모두 조사했다. 이제 다음과 같은 규칙을 이용해 정해진 순서대로 학생의 자리를 정하려고 한다. 한 칸에는 학생 한 명의 자리만 있을 수 있고, |r<sub>1</sub> - r<sub>2</sub>| + |c<sub>1</sub> - c<sub>2</sub>| = 1을 만족하는 두 칸이 (r<sub>1</sub>, c<sub>1</sub>)과 (r<sub>2</sub>, c<sub>2</sub>)를 인접하다고 한다.</p>
22+
23+
<ol>
24+
<li>비어있는 칸 중에서 좋아하는 학생이 인접한 칸에 가장 많은 칸으로 자리를 정한다.</li>
25+
<li>1을 만족하는 칸이 여러 개이면, 인접한 칸 중에서 비어있는 칸이 가장 많은 칸으로 자리를 정한다.</li>
26+
<li>2를 만족하는 칸도 여러 개인 경우에는 행의 번호가 가장 작은 칸으로, 그러한 칸도 여러 개이면 열의 번호가 가장 작은 칸으로 자리를 정한다.</li>
27+
</ol>
28+
29+
<p>예를 들어, N = 3이고, 학생 N<sup>2</sup>명의 순서와 각 학생이 좋아하는 학생이 다음과 같은 경우를 생각해보자.</p>
30+
31+
<table class="table table-bordered table-center-30">
32+
<thead>
33+
<tr>
34+
<th>학생의 번호</th>
35+
<th>좋아하는 학생의 번호</th>
36+
</tr>
37+
</thead>
38+
<tbody>
39+
<tr>
40+
<td>4</td>
41+
<td>2, 5, 1, 7</td>
42+
</tr>
43+
<tr>
44+
<td>3</td>
45+
<td>1, 9, 4, 5</td>
46+
</tr>
47+
<tr>
48+
<td>9</td>
49+
<td>8, 1, 2, 3</td>
50+
</tr>
51+
<tr>
52+
<td>8</td>
53+
<td>1, 9, 3, 4</td>
54+
</tr>
55+
<tr>
56+
<td>7</td>
57+
<td>2, 3, 4, 8</td>
58+
</tr>
59+
<tr>
60+
<td>1</td>
61+
<td>9, 2, 5, 7</td>
62+
</tr>
63+
<tr>
64+
<td>6</td>
65+
<td>5, 2, 3, 4</td>
66+
</tr>
67+
<tr>
68+
<td>5</td>
69+
<td>1, 9, 2, 8</td>
70+
</tr>
71+
<tr>
72+
<td>2</td>
73+
<td>9, 3, 1, 4</td>
74+
</tr>
75+
</tbody>
76+
</table>
77+
78+
<p>가장 먼저, 4번 학생의 자리를 정해야 한다. 현재 교실의 모든 칸은 빈 칸이다. 2번 조건에 의해 인접한 칸 중에서 비어있는 칸이 가장 많은 칸인 (2, 2)이 4번 학생의 자리가 된다.</p>
79+
80+
<table class="table table-bordered table-21608">
81+
<tbody>
82+
<tr>
83+
<td> </td>
84+
<td> </td>
85+
<td> </td>
86+
</tr>
87+
<tr>
88+
<td> </td>
89+
<td>4</td>
90+
<td> </td>
91+
</tr>
92+
<tr>
93+
<td> </td>
94+
<td> </td>
95+
<td> </td>
96+
</tr>
97+
</tbody>
98+
</table>
99+
100+
<p>다음 학생은 3번이다. 1번 조건을 만족하는 칸은 (1, 2), (2, 1), (2, 3), (3, 2) 이다. 이 칸은 모두 비어있는 인접한 칸이 2개이다. 따라서, 3번 조건에 의해 (1, 2)가 3번 학생의 자리가 된다.</p>
101+
102+
<table class="table table-bordered table-21608">
103+
<tbody>
104+
<tr>
105+
<td> </td>
106+
<td>3</td>
107+
<td> </td>
108+
</tr>
109+
<tr>
110+
<td> </td>
111+
<td>4</td>
112+
<td> </td>
113+
</tr>
114+
<tr>
115+
<td> </td>
116+
<td> </td>
117+
<td> </td>
118+
</tr>
119+
</tbody>
120+
</table>
121+
122+
<p>다음은 9번 학생이다. 9번 학생이 좋아하는 학생의 번호는 8, 1, 2, 3이고, 이 중에 3은 자리에 앉아있다. 좋아하는 학생이 가장 많이 인접한 칸은 (1, 1), (1, 3)이다. 두 칸 모두 비어있는 인접한 칸이 1개이고, 행의 번호도 1이다. 따라서, 3번 조건에 의해 (1, 1)이 9번 학생의 자리가 된다.</p>
123+
124+
<table class="table table-bordered table-21608">
125+
<tbody>
126+
<tr>
127+
<td>9</td>
128+
<td>3</td>
129+
<td> </td>
130+
</tr>
131+
<tr>
132+
<td> </td>
133+
<td>4</td>
134+
<td> </td>
135+
</tr>
136+
<tr>
137+
<td> </td>
138+
<td> </td>
139+
<td> </td>
140+
</tr>
141+
</tbody>
142+
</table>
143+
144+
<p>이번에 자리를 정할 학생은 8번 학생이다. (2, 1)이 8번 학생이 좋아하는 학생과 가장 많이 인접한 칸이기 때문에, 여기가 그 학생의 자리이다.</p>
145+
146+
<table class="table table-bordered table-21608">
147+
<tbody>
148+
<tr>
149+
<td>9</td>
150+
<td>3</td>
151+
<td> </td>
152+
</tr>
153+
<tr>
154+
<td>8</td>
155+
<td>4</td>
156+
<td> </td>
157+
</tr>
158+
<tr>
159+
<td> </td>
160+
<td> </td>
161+
<td> </td>
162+
</tr>
163+
</tbody>
164+
</table>
165+
166+
<p>7번 학생의 자리를 정해보자. 1번 조건을 만족하는 칸은 (1, 3), (2, 3), (3, 1), (3, 2)로 총 4개가 있고, 비어있는 칸과 가장 많이 인접한 칸은 (2, 3), (3, 2)이다. 행의 번호가 작은 (2, 3)이 7번 학생의 자리가 된다.</p>
167+
168+
<table class="table table-bordered table-21608">
169+
<tbody>
170+
<tr>
171+
<td>9</td>
172+
<td>3</td>
173+
<td> </td>
174+
</tr>
175+
<tr>
176+
<td>8</td>
177+
<td>4</td>
178+
<td>7</td>
179+
</tr>
180+
<tr>
181+
<td> </td>
182+
<td> </td>
183+
<td> </td>
184+
</tr>
185+
</tbody>
186+
</table>
187+
188+
<p>이런식으로 학생의 자리를 모두 정하면 다음과 같다.</p>
189+
190+
<table class="table table-bordered table-21608">
191+
<tbody>
192+
<tr>
193+
<td>9</td>
194+
<td>3</td>
195+
<td>2</td>
196+
</tr>
197+
<tr>
198+
<td>8</td>
199+
<td>4</td>
200+
<td>7</td>
201+
</tr>
202+
<tr>
203+
<td>5</td>
204+
<td>6</td>
205+
<td>1</td>
206+
</tr>
207+
</tbody>
208+
</table>
209+
210+
<p>이제 학생의 만족도를 구해야 한다. 학생의 만족도는 자리 배치가 모두 끝난 후에 구할 수 있다. 학생의 만족도를 구하려면 그 학생과 인접한 칸에 앉은 좋아하는 학생의 수를 구해야 한다. 그 값이 0이면 학생의 만족도는 0, 1이면 1, 2이면 10, 3이면 100, 4이면 1000이다.</p>
211+
212+
<p>학생의 만족도의 총 합을 구해보자.</p>
213+
214+
### 입력
215+
216+
<p>첫째 줄에 N이 주어진다. 둘째 줄부터 N<sup>2</sup>개의 줄에 학생의 번호와 그 학생이 좋아하는 학생 4명의 번호가 한 줄에 하나씩 선생님이 자리를 정할 순서대로 주어진다.</p>
217+
218+
<p>학생의 번호는 중복되지 않으며, 어떤 학생이 좋아하는 학생 4명은 모두 다른 학생으로 이루어져 있다. 입력으로 주어지는 학생의 번호, 좋아하는 학생의 번호는 N<sup>2</sup>보다 작거나 같은 자연수이다. 어떤 학생이 자기 자신을 좋아하는 경우는 없다.</p>
219+
220+
### 출력
221+
222+
<p>첫째 줄에 학생의 만족도의 총 합을 출력한다.</p>
223+
Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
import java.util.*;
2+
import java.io.*;
3+
4+
public class Main {
5+
static int N;
6+
static int[][] visited;
7+
static int[][] result;
8+
static int[][] input;
9+
10+
// 좌 상 우 하 (인접한 4방향)
11+
static int[] dx = {-1, 0, 1, 0};
12+
static int[] dy = {0, -1, 0, 1};
13+
14+
public static void main(String[] args) throws IOException {
15+
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
16+
17+
N = Integer.parseInt(br.readLine());
18+
visited = new int[N][N]; // 방문 여부
19+
result = new int[N][N]; // 자리 배치 결과
20+
input = new int[N * N][5]; // 학생 정보
21+
22+
// 학생 및 해당 학생이 좋아하는 학생 입력받기
23+
for (int i = 0; i < N * N; i++) {
24+
int[] line = Arrays.stream(br.readLine().split(" "))
25+
.mapToInt(Integer::parseInt)
26+
.toArray();
27+
for (int j = 0; j < 5; j++) {
28+
input[i][j] = line[j];
29+
}
30+
}
31+
32+
// 학생 순서대로 자리 배치
33+
for (int i = 0; i < N * N; i++) {
34+
placeStudent(input[i]);
35+
}
36+
37+
// 학생 만족도 계산
38+
System.out.println(calculateSatisfaction());
39+
}
40+
41+
// 학생 자리 배치
42+
public static void placeStudent(int[] line) {
43+
int maxLike = -1;
44+
int maxEmpty = -1;
45+
int resultX = -1, resultY = -1;
46+
47+
for (int i = 0; i < N; i++) {
48+
for (int j = 0; j < N; j++) {
49+
if (visited[i][j] == 0) { // 빈 자리 찾기
50+
int likeCount = 0, emptyCount = 0;
51+
52+
for (int k = 0; k < 4; k++) {
53+
int x = i + dx[k];
54+
int y = j + dy[k];
55+
56+
if (x >= 0 && x < N && y >= 0 && y < N) {
57+
if (result[x][y] == 0) {
58+
emptyCount++; // 비어있는 칸 개수
59+
} else {
60+
for (int z = 1; z < 5; z++) {
61+
if (result[x][y] == line[z]) {
62+
likeCount++; // 좋아하는 학생 카운트
63+
}
64+
}
65+
}
66+
}
67+
}
68+
69+
// 좋아하는 학생이 더 많은 칸을 우선
70+
if (likeCount > maxLike) {
71+
maxLike = likeCount;
72+
maxEmpty = emptyCount;
73+
resultX = i;
74+
resultY = j;
75+
}
76+
// 좋아하는 학생 수가 같다면, 비어있는 칸이 더 많은 곳 우선
77+
else if (likeCount == maxLike) {
78+
if (emptyCount > maxEmpty) {
79+
maxEmpty = emptyCount;
80+
resultX = i;
81+
resultY = j;
82+
}
83+
// 비어있는 칸 수도 같다면, 행 번호가 가장 작은 곳 선택
84+
else if (emptyCount == maxEmpty) {
85+
if (i < resultX || (i == resultX && j < resultY)) {
86+
resultX = i;
87+
resultY = j;
88+
}
89+
}
90+
}
91+
}
92+
}
93+
}
94+
95+
// 학생 자리 배치
96+
result[resultX][resultY] = line[0];
97+
visited[resultX][resultY] = 1;
98+
}
99+
100+
// 만족도 계산
101+
public static int calculateSatisfaction() {
102+
int sum = 0;
103+
HashMap<Integer, HashSet<Integer>> map = new HashMap<>();
104+
105+
// 학생 정보 맵으로 변환
106+
for (int[] student : input) {
107+
HashSet<Integer> set = new HashSet<>();
108+
for (int i = 1; i < 5; i++) {
109+
set.add(student[i]);
110+
}
111+
map.put(student[0], set);
112+
}
113+
114+
// 만족도 계산
115+
for (int i = 0; i < N; i++) {
116+
for (int j = 0; j < N; j++) {
117+
int student = result[i][j];
118+
int count = 0;
119+
120+
for (int k = 0; k < 4; k++) {
121+
int x = i + dx[k];
122+
int y = j + dy[k];
123+
124+
if (x >= 0 && x < N && y >= 0 && y < N) {
125+
if (map.get(student).contains(result[x][y])) {
126+
count++;
127+
}
128+
}
129+
}
130+
131+
// 만족도 점수 변환
132+
if (count > 0) {
133+
sum += (int) Math.pow(10, count - 1);
134+
}
135+
}
136+
}
137+
138+
return sum;
139+
}
140+
}

0 commit comments

Comments
 (0)