상어 초등학교(백준 21608번)
💡 **Check Point !
( 해당사항 ✓체크 )
막힘 없이 수월하게 풀린 문제인가?
1시간이내로 풀렸던 문제인가?
1시간 이상 or 며칠을 두고 풀어봤더니 풀린 문제인가?
시간을 써도 도무지 풀 수 없는 문제인가?
솔루션을 찾아봤는가?✓
난이도 체감
최상
상✓
중
하
이해도
완벽히 이해✓
다소 헷갈리는 부분들이 있음
이해 못함
문제
상어 초등학교에는 교실이 하나 있고, 교실은 N×N 크기의 격자로 나타낼 수 있다. 학교에 다니는 학생의 수는 N2명이다. 오늘은 모든 학생의 자리를 정하는 날이다. 학생은 1번부터 N2번까지 번호가 매겨져 있고, (r, c)는 r행 c열을 의미한다. 교실의 가장 왼쪽 윗 칸은 (1, 1)이고, 가장 오른쪽 아랫 칸은 (N, N)이다.
선생님은 학생의 순서를 정했고, 각 학생이 좋아하는 학생 4명도 모두 조사했다. 이제 다음과 같은 규칙을 이용해 정해진 순서대로 학생의 자리를 정하려고 한다. 한 칸에는 학생 한 명의 자리만 있을 수 있고, | r1 - r2 | + | c1 - c2 | = 1을 만족하는 두 칸이 (r1, c1)과 (r2, c2)를 인접하다고 한다. |
- 비어있는 칸 중에서 좋아하는 학생이 인접한 칸에 가장 많은 칸으로 자리를 정한다.
- 1을 만족하는 칸이 여러 개이면, 인접한 칸 중에서 비어있는 칸이 가장 많은 칸으로 자리를 정한다.
- 2를 만족하는 칸도 여러 개인 경우에는 행의 번호가 가장 작은 칸으로, 그러한 칸도 여러 개이면 열의 번호가 가장 작은 칸으로 자리를 정한다.
예를 들어, N = 3이고, 학생 N2명의 순서와 각 학생이 좋아하는 학생이 다음과 같은 경우를 생각해보자.
학생의 번호 | 좋아하는 학생의 번호 |
---|---|
4 | 2, 5, 1, 7 |
3 | 1, 9, 4, 5 |
9 | 8, 1, 2, 3 |
8 | 1, 9, 3, 4 |
7 | 2, 3, 4, 8 |
1 | 9, 2, 5, 7 |
6 | 5, 2, 3, 4 |
5 | 1, 9, 2, 8 |
2 | 9, 3, 1, 4 |
가장 먼저, 4번 학생의 자리를 정해야 한다. 현재 교실의 모든 칸은 빈 칸이다. 2번 조건에 의해 인접한 칸 중에서 비어있는 칸이 가장 많은 칸인 (2, 2)이 4번 학생의 자리가 된다.
4 | ||
다음 학생은 3번이다. 1번 조건을 만족하는 칸은 (1, 2), (2, 1), (2, 3), (3, 2) 이다. 이 칸은 모두 비어있는 인접한 칸이 2개이다. 따라서, 3번 조건에 의해 (1, 2)가 3번 학생의 자리가 된다.
3 | ||
---|---|---|
4 | ||
다음은 9번 학생이다. 9번 학생이 좋아하는 학생의 번호는 8, 1, 2, 3이고, 이 중에 3은 자리에 앉아있다. 좋아하는 학생이 가장 많이 인접한 칸은 (1, 1), (1, 3)이다. 두 칸 모두 비어있는 인접한 칸이 1개이고, 행의 번호도 1이다. 따라서, 3번 조건에 의해 (1, 1)이 9번 학생의 자리가 된다.
9 | 3 | |
---|---|---|
4 | ||
이번에 자리를 정할 학생은 8번 학생이다. (2, 1)이 8번 학생이 좋아하는 학생과 가장 많이 인접한 칸이기 때문에, 여기가 그 학생의 자리이다.
9 | 3 | |
---|---|---|
8 | 4 | |
7번 학생의 자리를 정해보자. 1번 조건을 만족하는 칸은 (1, 3), (2, 3), (3, 1), (3, 2)로 총 4개가 있고, 비어있는 칸과 가장 많이 인접한 칸은 (2, 3), (3, 2)이다. 행의 번호가 작은 (2, 3)이 7번 학생의 자리가 된다.
9 | 3 | |
---|---|---|
8 | 4 | 7 |
이런식으로 학생의 자리를 모두 정하면 다음과 같다.
9 | 3 | 2 |
---|---|---|
8 | 4 | 7 |
5 | 6 | 1 |
이제 학생의 만족도를 구해야 한다. 학생의 만족도는 자리 배치가 모두 끝난 후에 구할 수 있다. 학생의 만족도를 구하려면 그 학생과 인접한 칸에 앉은 좋아하는 학생의 수를 구해야 한다. 그 값이 0이면 학생의 만족도는 0, 1이면 1, 2이면 10, 3이면 100, 4이면 1000이다.
학생의 만족도의 총 합을 구해보자.
나의 풀이(정답 참고)
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
32
33
34
35
36
37
38
39
40
41
42
43
import sys
input=sys.stdin.readline
N=int(input().strip())
prefer_list=[]
for _ in range(N**2):
p=list(map(int,input().strip().split()))
prefer_list.append(p)
seats=[[0]*N for _ in range(N)]
dx=[-1,1,0,0]
dy=[0,0,-1,1]
for student in prefer_list:
tmp_seats_info=[]
for i in range(N):
for j in range(N):
if seats[i][j]==0:
empty=0
prefer_count=0
for d in range(4):
x=i+dx[d]
y=j+dy[d]
if 0<=x<N and 0<=y<N:
if seats[x][y]==0:
empty+=1
elif seats[x][y] in student[1:]:
prefer_count+=1
tmp_seats_info.append((i,j,prefer_count,empty))
tmp_seats_info.sort(key=lambda x:(-x[2],-x[3],x[0],x[1]))
seats[tmp_seats_info[0][0]][tmp_seats_info[0][1]]=student[0]
prefer_list.sort()
answer=0
for i in range(N):
for j in range(N):
count=0
student_num=seats[i][j]
for d in range(4):
x=i+dx[d]
y=j+dy[d]
if 0<=x<N and 0<=y<N:
if seats[x][y] in prefer_list[student_num-1]:
count+=1
if count:
answer+=10**(count-1)
print(answer)
- 위 문제는 아이디어를 떠올리는 것부터 쉽지 않았던 것 같다. 조건의 우선순위에 맞게 정보를 저장하고, 조건 우선순위에 따라 정렬을 해야 한다.
- 여기서 중요한 것은 시간복잡도를 고려해야 한다는 것이다. N의 최대값이 20이므로, 완전탐색 방식으로 풀어도 시간초과가 안난다는 것이다. 따라서 복잡하게 생각할 필요가 없었다.
- 각 자리를 확인하면서, 그 자리 근처에 선호하는 학생이 몇 명 있는지, 빈자리는 몇개인지, 행과 열은 어떻게 되는지 정보를 저장하고, 우선순위에 따라 정렬한 후 가장 우선순위가 높은 곳에 학생을 배치한다.