[BOJ] Q21608 상어초등학교
        
         
  
      [BOJ] Q21608 상어초등학교
Question
Language: Python
Difficulty: Gold 5
해당 문제는 주어진 조건을 정확하게 파악해서 이를 구현하는 것이 관건이다.
특정 학생을 배치하기 위해 아래의 조건들을 고려해야한다.
- 인접해 있는 칸에 좋아하는 학생이 가장 많이 있는 칸에 대해서 자리를 선택한다.
 - 만약 좋아하는 학생이 있는 인접한 칸이 가장 많은 칸이 여러 개인 경우, 인접한 빈칸이 가장 많은 칸을 선택한다.
 - 인접한 빈칸이 가장 많은 칸이 여러 개인 경우, 그러한 칸 중에서 행/열이 최소가 되는 칸으로 선택한다.
 
위의 조건들을 구현하는 과정 자체는 어렵지 않으나, 모든 조건을 정확하게 구현하는 것이 중요하다.
해당 문제는 행/열 값이 최대 20까지로 입력값이 작은 편에 속한다. 따라서, 모든 경우에 대해서 조사를 하더라도 주어진 시간 복잡도 내에 해결하는 것이 가능하다.
Solution
def calculate_satisfaction():
    sum_satisfaction=0
    for row in range(num):
        for col in range(num):
            student_number=graph[row][col]
            satisfaction=0
            for dir in range(4):
                new_row=row+dy[dir]
                new_col=col+dx[dir]
                if new_row < 0 or new_row>=num or new_col < 0 or new_col>=num:
                    continue
                
                if graph[new_row][new_col] in favorites[student_number]:
                    satisfaction+=1
            
            if satisfaction ==0 :
                sum_satisfaction+=0
            else:
                sum_satisfaction+=(10**(satisfaction-1))
    return sum_satisfaction
                
        
def solution():
    for student in student_order:
        best_row,best_col=0,0
        favorite_space_candidates=[[] for _ in range(5)] #후보칸
        #인접한 칸의 좋아하는 학생 수
        for row in range(num):
            for col in range(num):
                #빈자리가 아닌 경우 넘어간다.
                if graph[row][col] !=0:
                    continue
                favorite_count=0
        
                for dir in range(4):
                    new_row=row+dy[dir]
                    new_col=col+dx[dir]
                    if new_row < 0 or new_row>=num or new_col < 0 or new_col>=num:
                        continue
                    
                    if graph[new_row][new_col] in favorites[student]:
                        favorite_count+=1
                favorite_space_candidates[favorite_count].append((row,col))
        blank_space_candidates=[[] for _ in range(5)]
        #인접한 칸의 빈 칸 확인
        for i in range(4,-1,-1):
            if len(favorite_space_candidates[i])==0:
                continue
            elif len(favorite_space_candidates[i])==1:
                (best_row,best_col)=favorite_space_candidates[i][0]
                break
            
            for row,col in favorite_space_candidates[i]:
                blank_count=0
                for dir in range(4):
                    new_row=row+dy[dir]
                    new_col=col+dx[dir]
                    if new_row < 0 or new_row>=num or new_col < 0 or new_col>=num:
                        continue
                    
                    if graph[new_row][new_col]==0:
                        blank_count+=1
                blank_space_candidates[blank_count].append((row,col))
            break
        #여기까지도 자리가 설정이 안되는 경우 행/열이 가장 작은 자리 반환
        for i in range(4,-1,-1):
            if len(blank_space_candidates[i])==0:
                continue
            elif len(blank_space_candidates[i])==1:
                (best_row,best_col)=blank_space_candidates[i][0]
                break
            blank_space_candidates[i].sort(key=lambda x: (x[0],x[1]))
            (best_row,best_col)=blank_space_candidates[i][0]
            break
        graph[best_row][best_col]=student
    
    return calculate_satisfaction()
    
    
if __name__ == "__main__":
    num=0
    favorites=[]
    graph=[]
    student_order=[]
    dy=[-1,0,1,0]
    dx=[0,1,0,-1]
    num=int(input())
    graph=[[0] * num for _ in range(num)]
    favorites=[[] for _ in range(num**2 +1)]
    for _ in range(num**2):
        student_num,s1,s2,s3,s4=map(int,input().split())
        student_order.append(student_num)
        favorites[student_num]=[s1,s2,s3,s4]
    print(solution())
      
댓글남기기