우리는 N x N 배열도 필요하므로 모든 값이 0인 배열 arr을 만들어주고, 입력값을 받아주면 됩니다.
여기서 N*N줄을 입력받을 때, 학생의 번호와 좋아하는 학생들을 딕셔너리로 저장하면 편합니다.
n =int(input())arr = [[0]* n for _ inrange(n)]student ={}for i inrange(n*n): x, s1, s2, s3, s4 =map(int,input().split()) student[x]= [s1, s2, s3, s4]
2. 좋아하는 학생이 가장 많이 인접한 칸
빈칸에서 좋아하는 학생이 가장 많이 인접한 칸을 찾아주면 됩니다.
우리는 좋아하는 학생이 가장 많이 인접한 칸이 여러 개일 수도 있으므로 love라는 리스트를 하나 만들어서 [인접한 좋아하는 학생 수, 좌표를 넣어줄 큐] 형태로 저장을 해야 합니다.
from collections import dequen =int(input())arr = [[0]* n for _ inrange(n)]student ={}for i inrange(n*n): x, s1, s2, s3, s4 =map(int,input().split()) student[x]= [s1, s2, s3, s4]for t inrange(n*n): love = [0,deque()]
그래서 위와 같이 collections.deque를 불러오고, 첫 번째 단계는 love라고 해서 초기값은 [ 0, deque() ]로 만들어줍니다.
그리고 이제 (0, 0)에서 (n-1, n-1)중에 빈칸만 확인해서 초깃값을 업데이트하면 됩니다.
예를 들어서 love = [ 2, deque([(0, 0), (1, 2)])] 로 되어 있으면 현재 좋아하는 사람이 가장 인접된 수는 2이고, 그 칸은 (0, 0)과 (1, 2)가 있다는 뜻입니다. 만약 (3, 4)에서 좋아하는 사람이 가장 인접된 수가 3명이 된다면 love = [ 3, deque([(3,4)])] 가 됩니다.
이번 문제에는 상하좌우가 필요하므로 dx, dy 를 만들어줍니다.
from collections import dequedx, dy = [1,-1,0,0], [0,0,1,-1]n =int(input())arr = [[0]* n for _ inrange(n)]student ={}for i inrange(n*n): x, s1, s2, s3, s4 =map(int,input().split()) student[x]= [s1, s2, s3, s4]for t in student.keys(): love = [0,deque()]
그리고 상하좌우 인접한 자리를 확인할 때, 배열의 범위가 넘어가지 않는지 확인해야 하므로 범위 내에 있으면 True, 아니면 False를 반환하는 check 함수를 만들어주면 됩니다.
defcheck(x,y):if0<= x < n and0<= y < n:returnTruereturnFalsefrom collections import dequedx, dy = [1,-1,0,0], [0,0,1,-1]n =int(input())arr = [[0]* n for _ inrange(n)]student ={}for i inrange(n*n): x, s1, s2, s3, s4 =map(int,input().split()) student[x]= [s1, s2, s3, s4]for t in student.keys(): love = [0,deque()]
이제 for문을 돌려서 빈칸에서 좋아하는 사람이 가장 많이 인접한 칸을 찾으면 됩니다.
주의할 점
본문 세 번째 조건에서는 자리가 여러 개라면 1순위는 행의 번호가 가장 작은 칸을, 2순위는 열의 번호가 가장 작은 칸을 선택해야 합니다.
그래서 이건 정렬을 해야 한다고 생각할 수 있겠지만, 아래와 같이 탐색하게 되면 정렬을 하지 않아도 무조건 행의 번호가 작은 순, 행의 번호가 같으면 열의 번호가 작은 순으로 정렬될 수 있다는 것을 알 수 있습니다.
for i inrange(n):for j inrange(n): blah blah
defcheck(x,y):if0<= x < n and0<= y < n:returnTruereturnFalsefrom collections import dequedx, dy = [1,-1,0,0], [0,0,1,-1]n =int(input())arr = [[0]* n for _ inrange(n)]student ={}for i inrange(n*n): x, s1, s2, s3, s4 =map(int,input().split()) student[x]= [s1, s2, s3, s4]for t in student.keys(): love = [0,deque()]for x inrange(n):for y inrange(n):if arr[x][y] ==0: val =0for i inrange(4): nx, ny = x + dx[i], y + dy[i]ifcheck(nx, ny)and arr[nx][ny] in student[t]: val +=1
위와 같은 코드처럼 빈칸(if arr[x][y] == 0)일 때, (x, y)를 (nx, ny)로 만들어서 범위 내에 있는지 확인 후에 좋아하는 학생들 목록에 arr[nx][ny]가 들어가는지 확인해주면 됩니다. 들어가 있으면 val += 1을 해주고, 아니면 그냥 넘어가면 됩니다.
그리고 이제 val이 love[0]과 같으면 큐에 좌표를 넣어주고, val > love[0]이면 love = [ val, deque([(좌표)])]로 새로 만들어주면 됩니다.
defcheck(x,y):if0<= x < n and0<= y < n:returnTruereturnFalsefrom collections import dequedx, dy = [1,-1,0,0], [0,0,1,-1]n =int(input())arr = [[0]* n for _ inrange(n)]student ={}for i inrange(n*n): x, s1, s2, s3, s4 =map(int,input().split()) student[x]= [s1, s2, s3, s4]for t in student.keys():# 좋아하는 학생이 가장 많이 인접한 칸 찾기 love = [0,deque()]for x inrange(n):for y inrange(n):if arr[x][y] ==0: val =0for i inrange(4): nx, ny = x + dx[i], y + dy[i]ifcheck(nx, ny)and arr[nx][ny] in student[t]: val +=1if val == love[0]: love[1].append((x,y))if val > love[0]: love = [val,deque([(x,y)])]
이렇게 해서 첫 번째 조건을 완료하였습니다.
이제 큐에 들어 있는 원소의 개수가 2개 이상이면 두 번째 조건으로 넘어가고, 1개이면 바로 자리를 배정하면 됩니다.
그런데 어차피 원소의 개수가 1개이면, 두 번째 조건을 돌려도 원소가 1개만 있으므로 저 값으로 결정하게 됩니다.
그래서 저는 if문 없이 그냥 코드를 추가하겠습니다.
iflen(love[1])==1: x, y = love[1].popleft() arr[x][y] = student[t][0]continue
원소의 개수가 1개일 때의 바로 자리를 배정해주는 조건문을 추가하고 싶은 분은 위 코드를 넣어주시면 됩니다.
3. 빈칸이 가장 많이 인접한 칸 찾기
이제 love[1]의 큐를 가지고 빈칸이 가장 많이 인접한 칸을 찾아주면 됩니다.
이번에는 blank라는 리스트에 값을 저장하는데, blank의 값은 [빈칸이 가장 많이 있는 개수, 좌표들을 저장할 리스트] 로 만들어주면 됩니다.
첫 번째 조건과는 다르게 큐가 아닌 리스트로 저장해주는 이유는 굳이 큐를 사용할 필요는 없기 때문입니다.
defcheck(x,y):if0<= x < n and0<= y < n:returnTruereturnFalsefrom collections import dequedx, dy = [1,-1,0,0], [0,0,1,-1]n =int(input())arr = [[0]* n for _ inrange(n)]student ={}for i inrange(n*n): x, s1, s2, s3, s4 =map(int,input().split()) student[x]= [s1, s2, s3, s4]for t in student.keys():# 좋아하는 학생이 가장 많이 인접한 칸 찾기 love = [0,deque()]for x inrange(n):for y inrange(n):if arr[x][y] ==0: val =0for i inrange(4): nx, ny = x + dx[i], y + dy[i]ifcheck(nx, ny)and arr[nx][ny] in student[t]: val +=1if val == love[0]: love[1].append((x,y))if val > love[0]: love = [val,deque([(x,y)])]# 빈칸이 가장 많은 자리 찾기 blank = [0, []]
이번엔 큐에서 원소를 빼서 확인하므로 while문을 이용하여 blank에 값을 넣어주면 됩니다.
defcheck(x,y):if0<= x < n and0<= y < n:returnTruereturnFalsefrom collections import dequedx, dy = [1,-1,0,0], [0,0,1,-1]n =int(input())arr = [[0]* n for _ inrange(n)]student ={}for i inrange(n*n): x, s1, s2, s3, s4 =map(int,input().split()) student[x]= [s1, s2, s3, s4]for t in student.keys():# 좋아하는 학생이 가장 많이 인접한 칸 찾기 love = [0,deque()]for x inrange(n):for y inrange(n):if arr[x][y] ==0: val =0for i inrange(4): nx, ny = x + dx[i], y + dy[i]ifcheck(nx, ny)and arr[nx][ny] in student[t]: val +=1if val == love[0]: love[1].append((x,y))if val > love[0]: love = [val,deque([(x,y)])]# 빈칸이 가장 많은 자리 찾기 blank = [0, []]while love[1]: x, y = love[1].popleft() val =0for i inrange(4): nx, ny = x + dx[i], y + dy[i]ifcheck(nx, ny)and arr[nx][ny] ==0: val +=1
val의 값이 blank[0]과 같으면 blank[1]에 좌표를 추가해주고, val > blank[0]이면 blank = [val, [좌표]]로 수정해주면 됩니다.
defcheck(x,y):if0<= x < n and0<= y < n:returnTruereturnFalsefrom collections import dequedx, dy = [1,-1,0,0], [0,0,1,-1]n =int(input())arr = [[0]* n for _ inrange(n)]student ={}for i inrange(n*n): x, s1, s2, s3, s4 =map(int,input().split()) student[x]= [s1, s2, s3, s4]for t in student.keys():# 좋아하는 학생이 가장 많이 인접한 칸 찾기 love = [0,deque()]for x inrange(n):for y inrange(n):if arr[x][y] ==0: val =0for i inrange(4): nx, ny = x + dx[i], y + dy[i]ifcheck(nx, ny)and arr[nx][ny] in student[t]: val +=1if val == love[0]: love[1].append((x,y))if val > love[0]: love = [val,deque([(x,y)])]# 빈칸이 가장 많은 자리 찾기 blank = [0, []]while love[1]: x, y = love[1].popleft() val =0for i inrange(4): nx, ny = x + dx[i], y + dy[i]ifcheck(nx, ny)and arr[nx][ny] ==0: val +=1if val == blank[0]: blank[1].append((x,y))if val > blank[0]: blank = [val,deque([(x,y)])]
이제 blank[1]에 있는 첫 번째 값은 무조건 본문 1, 2 조건을 만족하면서 행의 번호와 열의 번호가 가장 작은 좌표입니다.
그래서 blank[1]의 첫 번째 값 좌표에 t번째 학생의 번호인 student[t][0]을 저장하면 되겠습니다.
defcheck(x,y):if0<= x < n and0<= y < n:returnTruereturnFalsefrom collections import dequedx, dy = [1,-1,0,0], [0,0,1,-1]n =int(input())arr = [[0]* n for _ inrange(n)]student ={}for i inrange(n*n): x, s1, s2, s3, s4 =map(int,input().split()) student[x]= [s1, s2, s3, s4]for t in student.keys():# 좋아하는 학생이 가장 많이 인접한 칸 찾기 love = [0,deque()]for x inrange(n):for y inrange(n):if arr[x][y] ==0: val =0for i inrange(4): nx, ny = x + dx[i], y + dy[i]ifcheck(nx, ny)and arr[nx][ny] in student[t]: val +=1if val == love[0]: love[1].append((x,y))if val > love[0]: love = [val,deque([(x,y)])]# 빈칸이 가장 많은 자리 찾기 blank = [0, []]while love[1]: x, y = love[1].popleft() val =0for i inrange(4): nx, ny = x + dx[i], y + dy[i]ifcheck(nx, ny)and arr[nx][ny] ==0: val +=1if val == blank[0]: blank[1].append((x,y))if val > blank[0]: blank = [val,deque([(x,y)])]# 좌석 배정 x, y = blank[0] arr[x][y] = t
4. 점수 계산하기
이제 좌석을 다 배정했으면 점수를 더해주면 됩니다. 본문에 있는 점수 배점대로 score라는 배열을 만들어서 score = [0, 1, 10, 100, 1000]을 만들어주고, 인접하고 있는 좋아하는 학생 수대로 ans에 점수를 더해주면 됩니다.
그리고 ans를 출력하면 끝나게 됩니다.
defcheck(x,y):if0<= x < n and0<= y < n:returnTruereturnFalsefrom collections import dequedx, dy = [1,-1,0,0], [0,0,1,-1]n =int(input())arr = [[0]* n for _ inrange(n)]student ={}for i inrange(n*n): x, s1, s2, s3, s4 =map(int,input().split()) student[x]= [s1, s2, s3, s4]for t in student.keys():# 좋아하는 학생이 가장 많이 인접한 칸 찾기 love = [0,deque()]for x inrange(n):for y inrange(n):if arr[x][y] ==0: val =0for i inrange(4): nx, ny = x + dx[i], y + dy[i]ifcheck(nx, ny)and arr[nx][ny] in student[t]: val +=1if val == love[0]: love[1].append((x,y))if val > love[0]: love = [val,deque([(x,y)])]# 빈칸이 가장 많은 자리 찾기 blank = [0, []]while love[1]: x, y = love[1].popleft() val =0for i inrange(4): nx, ny = x + dx[i], y + dy[i]ifcheck(nx, ny)and arr[nx][ny] ==0: val +=1if val == blank[0]: blank[1].append((x,y))if val > blank[0]: blank = [val, [(x,y)]] x, y = blank[1][0] arr[x][y] = t# 점수 구하기ans =0score = [0,1,10,100,1000]for x inrange(n):for y inrange(n): val =0for i inrange(4): nx, ny = x+dx[i],y+dy[i]ifcheck(nx, ny)and arr[nx][ny] in student[arr[x][y]]: val +=1 ans += score[val]print(ans)
다른 방법
조건 1과 조건 2를 합쳐서 만들 수도 있습니다.
defcheck(x,y):if0<= x < n and0<= y < n:returnTruereturnFalsedx, dy = [1,-1,0,0], [0,0,1,-1]n =int(input())arr = [[0]* n for _ inrange(n)]student ={}for i inrange(n*n): x, s1, s2, s3, s4 =map(int,input().split()) student[x]= [s1, s2, s3, s4]for t in student.keys():# 좋아하는 학생이 가장 많이 인접한 칸이면서 빈칸이 많은 칸 찾기 best = [0,0, []] # 좋아하는 학생 수, 빈칸의 수, 좌표for x inrange(n):for y inrange(n):if arr[x][y] ==0: love =0 zero =0for i inrange(4): nx, ny = x + dx[i], y + dy[i]ifcheck(nx, ny):if arr[nx][ny] in student[t]: love +=1if arr[nx][ny] ==0: zero +=1if love == best[0]and zero == best[1]: best[2].append((x,y))if love > best[0]or (love == best[0]and zero > best[1]): best = [love, zero, [(x,y)]] x, y = best[2][0] arr[x][y] = t# 점수 구하기ans =0score = [0,1,10,100,1000]for x inrange(n):for y inrange(n): val =0for i inrange(4): nx, ny = x+dx[i],y+dy[i]ifcheck(nx, ny)and arr[nx][ny] in student[arr[x][y]]: val +=1 ans += score[val]print(ans)