본문 바로가기
코딩테스트 문제풀이/beakjoon

[백준] 21608 상어 초등학교

by merona99 2021. 8. 31.
반응형

백준 21608번 상어 초등학교

구현


실버1 치고 생각보다 어려웠던 문제
문제를 풀다보니 이전엔 dfs와 같은 그래프가 어렵다 생각했는데 이제는 구현이 가장 까다롭고 복잡한 것 같다.


[문제]



노란 부분이 구현의 핵심이 되는 알고리즘 이다.
1,2번은 같이 구할 수 있고 마지막에 학생이 인접한 수, 비어있는 칸수, x행, y열로 정렬을 해주면 된다.



위에까지 좌표를 완성한 후 만족도까지 구해야 한다.
좌표만큼 반복문을 돌리고 해당 값만큼 조건문으로 값을 더해주자.


[과정]


※ 좌표 저장하기

1. 학생수(students)만큼 반복
1-1) 좌표만큼(n*n)만큼 반복
1-2) 해당 좌표가 아무값도 없을시(-1) 인접한 경로(상하좌우)를 탐색
1-3) 배열(arr)에 인접한 학생수, 인접한 빈칸 수, x좌표, y좌표를 저장 (cnt, empty, x, y)
1-4) lambda 함수를 사용하여 학생수, 빈칸수는 내림차순, x좌표, y좌표는 오름차순으로 순서대로 정렬


※ 만족도 구하기

2. n*n만큼 반복
2-1) 해당 좌표의 값(num)을 구하여 변수(data)에 해당 학생을 좋아하는 번호를 저장
2-2) 상하좌우를 비교하여 인접한 좌표값의 값이 data에 있으면 cnt에 1추가
2-3) 인접한 학생수(cnt)에 따른 별개의 만족도 값을 변수(ans)에 저장하여 최종 출력



※ 테스트 케이스는 맞는데 '틀렸습니다.' 뜨는 경우 ※
나의 경우였다.

나의 코드중 '# 수정' 부분을 보면 기존에는 for문이 없었는데 for문을 추가해줬다.
그 이유는 해당 번호 주변에 좋아하는 학생들이 없는데 앉을 자리가 많은 경우 첫번째 자리에 값이 계속 덮어 씌워지는 오류가 있었다.




해당 테스트 케이스를 돌려보고 확인해보자.

case1)

4
1 1 2 3 4
2 1 2 3 4
3 1 2 3 4
4 1 2 3 4
5 1 2 3 4
6 1 2 3 4
7 1 2 3 4
8 1 2 3 4
9 1 2 3 4
10 1 2 3 4
11 1 2 3 4
12 1 2 3 4
13 1 2 3 4
14 1 2 3 4
15 1 2 3 4
16 1 2 3 4

답: 48

완성된 배열

13 5 9 14
6 1 2 7
10 3 4 11
15 8 12 16



출처: https://jamluck.tistory.com/5 [잼럭의 기록저장소]



case2)

3
1 2 3 4 5
2 1 3 4 5
3 1 2 4 5
4 1 2 3 5
5 1 2 3 4
6 1 2 3 4
7 1 2 3 4
8 1 2 3 4
9 1 2 3 4

답 : 134



출처: https://jamluck.tistory.com/5 [잼럭의 기록저장소]





[소스코드]

 

# 상어 초등학교

n = int(input())
students = [0] * (n*n)

for i in range(n*n):
    students[i] = list(map(int, input().split()))
    
graph = [[-1]*n for i in range(n)]
nx = [1,-1,0,0]
ny = [0,0,1,-1]

# 좌표 저장
for student in students:
    arr = []
    for i in range(n):
        for j in range(n):
            cnt = 0
            empty = 0            
            if graph[i][j] == -1:
                for k in range(4):
                    x = i + nx[k]
                    y = j + ny[k]
                    if x < 0 or x >= n or y < 0 or y >= n:
                        continue
                    if graph[x][y] == -1:
                        empty += 1
                    elif graph[x][y] in student[1:]:
                        cnt += 1
            arr.append((cnt,empty,i,j))

    # 수정
    result = sorted(arr, key = lambda x : (-x[0], -x[1], x[2], x[3]))
    for r in result:
        if graph[r[2]][r[3]] == -1:
            graph[r[2]][r[3]] = student[0]
            break

# 만족도 구하기
ans = 0
for i in range(n):
    for j in range(n):
        for s in students:
            if s[0] == graph[i][j]:
                num = s
                data = s[1:]          
        sat = 0       
        for k in range(4):
            x = i + nx[k]
            y = j + ny[k]
            if x < 0 or x >= n or y < 0 or y >= n:
                continue
            if graph[x][y] in data:
                sat += 1
        if sat != 0:
            ans += 10 ** (sat-1)
print(ans)






[정답]

 

 

 

 

 


 

 

[두번째로 풀었던 코드]

 

# 2022.03.18 상어초등학교
# 알고리즘 스터디 1주차

n = int(input())
arr = [[0]*n for _ in range(n)]

student = []
for _ in range(n*n):
    m = list(map(int, input().split()))
    student.append(m)

dx = [1,-1,0,0]
dy = [0,0,-1,1]
    
# 좋아하는 학생이 인접한 수, 인접한칸중 비어있는칸수, 행, 열 순
for s in student:
    s1 = s[0]
    s2 = s[1:]
    maps= [] # 계산완료된 것
    
    for i in range(n):
        for j in range(n):
            # 첫번째 두번째
            cnt_1 = 0
            cnt_2 = 0
            
            if arr[i][j] != 0:
                continue
            
            for k in range(4):
                x = i + dx[k]
                y = j + dy[k]
                if x < 0 or x >= n or y < 0 or y >= n:
                    continue
                if arr[x][y] in s2:
                    cnt_1 += 1
                elif arr[x][y] == 0:
                    cnt_2 += 1
            maps.append([cnt_1, cnt_2, i, j])
    # 한사이클
    # 람다로 정렬
##    print('이전의 maps', maps)
    maps.sort(key = lambda x:(-x[0],-x[1],x[2],x[3]))
##    print('maps',maps)
    data = maps[0]
##    print('data',data)
    arr[data[2]][data[3]] = s1
##    print('arr',arr)
##    print()
    
                
# 만족도구하기
result = 0
for i in range(n):
    for j in range(n):
        cnt = 0
        for k in range(4):
            x = i + dx[k]
            y = j + dy[k]
            if x < 0 or x >= n or y < 0 or y >= n:
                continue
            for s3 in student:
                if arr[i][j] == s3[0]:
                    if arr[x][y] in s3[1:]:
                        cnt+=1
                        
        if cnt == 0:
            result += 0
        elif cnt == 1:
            result += 1
        elif cnt == 2:
            result += 10
        elif cnt == 3:
            result += 100
        elif cnt == 4:
            result += 1000
print(result)

스터디를 하면서 다시한번 풀어보게 되었다.

이미 한번 풀었던 거였는데 1시간 반이나 걸렸다...ㅜㅜ

 

 

[원큐로 정답]

그래도 한번 풀었었다고 풀이과정이 좀 기억이 났다.

처음 풀었을때는 몇번틀리고 맞았는데 이번엔 한번에 푼것에 의의를 둔다!ㅎㅎ

 

 

반응형

'코딩테스트 문제풀이 > beakjoon' 카테고리의 다른 글

[ICPC] 대학생 프로그래밍 경진대회  (0) 2021.10.09
[백준] 2346 풍선 터뜨리기  (0) 2021.09.27
[백준] 18258 큐 2  (0) 2021.08.20
[백준] 1158 요세푸스 문제  (0) 2021.08.20
[백준] 14502 연구소  (0) 2021.08.16

댓글