삼성 SW역량테스트 기출 / 2023 상반기 오후 1번 문제 메이즈러너 - 회전, BFS, 가장 작은 정사각형 찾고 회전 / Python 파이썬

2024. 10. 9. 19:47·coding test - python/Code Tree
728x90
반응형

 

*문제 출처는 코드트리에 있습니다.

 

삼멘

문제 제목: 메이즈러너

문제 사이트: https://www.codetree.ai/training-field/frequent-problems/problems/maze-runner/description?page=2&pageSize=5

 

코드트리 | 코딩테스트 준비를 위한 알고리즘 정석

국가대표가 만든 코딩 공부의 가이드북 코딩 왕초보부터 꿈의 직장 코테 합격까지, 국가대표가 엄선한 커리큘럼으로 준비해보세요.

www.codetree.ai

 


더보기

sudo

""" # 벽 -> 참가자 이동X 회전할때 내구도 깎임 0: 빈칸
# 출구 도착시 탈출

# 참가자 이동 로직
# 움직일 수 있는 칸 2칸이상 -> 상하로 움직임
# 출구까지 최단거리
# 한칸에 참가자 두명 가능

# 미로 회전 로직
def move_man():
    queue = deque([])
    # 출구와 가까운 곳으로 이동 ex,ey : 출구 좌표
    direct = ((1,0),(-1,0),(0,1),(0,-1))
    MIN = float('inf')
    for i in range(4)
        x = qx + direct[i][0]
        y = qy + direct[i][1]

        dist = abs(x - ex) + abs(y - ey)
        if dist < MIN:
            # 해당 참가자는 작은 좌표로 이동

def squere():# 출구와 한명이상의 참가자가 있는 정사각형 구하는 로직
    ex, ey # 출구 좌표
    # 사람 좌표
    #
    for i in range(N):
        for j in range(N):
            if maps[i][j] == 사람이면:

    return
def rotate_map():
    # 한 명 이상의 참가자와 출구를 포함한 가장 작은 정사각형
    sr,sc,size = squere() # 정사각형 시작좌표와 크기
    # 시계방향 회전
    for i in range(sr,sr + size):
        for j in range(sc,sc+size):
            maps[j][size-1+i] = maps[i][j]
            if maps[j][size-1+i]>0:
                maps[j][size-1+i] -= 1 # 내부에 있는 벽 내구도 깎기

while K>0:
    move_man()
    rotate_map()
    if man == 다 탈출:
        break
    K -= 1
"""

 

나의 풀이

- 테케 7번에서 막힌다..

 

10 10 7
0 0 0 0 0 0 5 1 0 0
0 0 0 0 0 0 0 0 9 0
0 0 0 0 0 0 0 0 9 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 5 0 0
0 0 0 0 0 0 0 0 0 0
3 0 0 0 0 0 7 0 0 0
0 0 0 0 0 0 0 0 8 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 1 0 0 0 0 0
3 1
1 2
9 3
5 3
9 9
4 9
4 7
4 7
1 3
9 6
2 4
from collections import deque
N,M,K = map(int,input().split())
maps = [list(map(int,input().split())) for _ in range(N)]
man_point = [list(map(int,input().split())) for _ in range(M)]


ex, ey = map(int,input().split()) # 출구 좌표
ex, ey = ex - 1, ey - 1

move = 0
# 미로 회전 로직
def move_man(man):
    global move, maps
    queue = deque(man)
    # 출구와 가까운 곳으로 이동 ex,ey : 출구 좌표
    direct = [(-1, 0), (1, 0), (0, -1), (0, 1)]  # 상하좌우
    # 각 참가자들은 1초에 한칸씩 움직이는거

    while queue:
        q = queue.popleft()
        MIN = float('inf')
        qx, qy = q[0],q[1]
        MIN_point = [qx,qy]

        for i in range(4):
            x = qx + direct[i][0]
            y = qy + direct[i][1]
            if x == ex and y == ey:
                MIN_point = [x, y]
                # 참가자 탈출하면 next는 없음
                break
            # 출구와 가까워지는 방향에 대해 멀어지면 이동 X
            if 0 <= x < N and 0 <= y < N and maps[x][y] <= 0:
                move_dist = abs(x - ex) + abs(y - ey)
                origin_dist = abs(qx - ex) + abs(qy - ey) # 이동 전 거리
                if move_dist < origin_dist: # 이동한 거리가 이동 전 거리보다 출구에 가깝다면
                    if move_dist < MIN:
                        MIN = move_dist
                        MIN_point = [x,y]

        nx, ny = MIN_point[0], MIN_point[1]

        if maps[nx][ny] != 10 and [nx,ny] != [qx,qy]:
            cnt = maps[qx][qy]
            maps[nx][ny] = maps[nx][ny] + cnt
            maps[qx][qy] = 0
            move += cnt
        elif maps[nx][ny] == 10:
            cnt = maps[qx][qy]
            move += cnt
            maps[qx][qy] = 0

    return

def square():  # 출구와 한명이상의 참가자가 있는 정사각형 구하는 로직
    MIN_size = float('inf')
    MIN_point = []
    for i in range(len(man_point)):
        x,y = man_point[i][0] ,man_point[i][1]  # 사람 좌표
        # 가로, 세로 길이 중 긴것이 정사각형 한 변의 길이가됨
        size = max(abs(x-ex),abs(y-ey)) + 1
        if MIN_size > size:
            MIN_point = [x,y]
            MIN_size = size
        elif MIN_size == size and MIN_point[0] > x:
            MIN_point = [x,y]
        elif MIN_size == size and MIN_point[0] == x and MIN_point[1] > y:
            MIN_point = [x,y]

    # 먼저 직사각형 영역만큼 확인
    min_x = min(MIN_point[0], ex)
    min_y = min(MIN_point[1], ey)

    max_x = max(MIN_point[0], ex)
    max_y = max(MIN_point[1], ey)

    start_x, start_y, end_x, end_y = min_x, min_y, max_x, max_y
    if abs(min_y - max_y) == abs(min_x - max_x):
        start_x,start_y = min_x,min_y
        end_x,end_y = max_x,max_y

    # 직사각형 영역에서 짧은 영역을 위나 아래로 size 길이가 되게 만들어야함
    elif abs(min_y - max_y) > abs(min_x - max_x): # y보다 작은 x 값을 늘려준다
        extend_size = MIN_size - (abs(min_x - max_x) + 1)
        start_x = min_x - extend_size # 우선 왼쪽으로 확장해본다
        end_x = max_x

        if start_x < 0: # 위쪽으로 못밀면 못 민만큼 아래쪽으로 확장
            end_x = min(N-1,max_x + abs(start_x))
            start_x = 0


    elif abs(min_y - max_y) < abs(min_x - max_x): # x보다 작은 y값을 늘려준다
        extend_size = MIN_size - (abs(min_y - max_y) + 1)
        start_y = min_y - extend_size
        end_y = max_y
        if start_y < 0:  # 왼쪽으로 못밀면 못 민만큼 오른쪽으로 확장
            end_y = min(N - 1, max_y + abs(start_y))
            start_y = 0

    return start_x,start_y,end_x,end_y

def rotate_map():
    global maps, ex, ey, man_point
    # 한 명 이상의 참가자와 출구를 포함한 가장 작은 정사각형
    sr, sc, er, ec = square()  # 정사각형 시작 좌표와 끝 좌표
    size = er - sr + 1  # 정사각형의 크기는 sr, er 사이의 차이 + 1
    new_maps = [[0]*size for i in range(size)]  # 회전된 결과를 저장할 새로운 배열

    # 시계 방향으로 회전
    for i in range(size):
        for j in range(size):
            new_maps[j][size - 1 - i] = maps[sr + i][sc + j]  # 좌표 변환하여 회전
            if 0 < new_maps[j][size - 1 - i] < 10:
                new_maps[j][size - 1 - i] -= 1  # 내부에 있는 벽 내구도 깎기
    # 근데 사람도 같이 회전해야함

    # 회전한 결과를 원래 배열에 반영
    for i in range(size):
        for j in range(size):
            maps[sr+i][sc+j] = new_maps[i][j]
            # 출구 좌표 갱신 (-1이 출구라면)
            if maps[sr+i][sc+j] == 10:
                ex, ey = sr+i, sc+j
    # print(f'size: {size}, r:{sr},c:{sc}')
    # print(f'exit: {ex},{ey}')

for i in range(len(man_point)):
    man_point[i][0] -= 1
    man_point[i][1] -= 1
    x = man_point[i][0]
    y = man_point[i][1]
    maps[x][y] -= 1
maps[ex][ey] = 10

while K>0:
    move_man(man_point)
    man_point = []
    for i in range(N):
        for j in range(N):
            if maps[i][j] < 0:
                man_point.append([i,j])
    if man_point == []:
        break
    rotate_map()
    man_point = []
    for i in range(N):
        for j in range(N):
            if maps[i][j] < 0:
                man_point.append([i,j])
    if man_point == []:  # 다 탈출하면
        break


    K -= 1
# 모든 참가자들의 이동 거리 합과 출구 좌표 출력
print(-1*move)
print(ex+1,ey+1)

정사각형을 완전탐색으로 찾아서 구현

 

자자 완창한다.

동시에 움직이는 상황이면 뭐다? 복사 or 0으로 새로운 배열 만들기

무조건 배열을 복사하거나 새로 만들어서 최종적으로 움직인 다음

전역변수에 다시 넣어준다.

 

한번 더 완창한다.

 

회전하는 상황이면 뭐다? 복사 or 0으로 새로운 배열 만들기

90도 회전하는 코드는 뭐다?

new_maps = [x[:] for x in maps] # maps는 원본 이라 하고 복사하기
for i in range(N):
	for j in range(N):
    	new_maps[i][j] = maps[N-1-j][i]

maps = new_maps

 

머리 팍! 치면 코드 팍! 나와야한다.

 

 

from collections import deque
N,M,K = map(int,input().split())
maps = [list(map(int,input().split())) for _ in range(N)]
man_point = [list(map(int,input().split())) for _ in range(M)]


ex, ey = map(int,input().split()) # 출구 좌표
ex, ey = ex - 1, ey - 1
remain_man = M # 모든 참가자가 나갔는지 확인하기 위함
def move():
    global move_cnt, remain_man, maps
    # 출구와 가까워지는 방향으로
    # 머물러 있던 칸 보다 출구까지의 최단거리가 가까워야함
    direction = ((1,0),(-1,0),(0,1),(0,-1))
    new_maps = [x[:] for x in maps]

    for i in range(N):
        for j in range(N):
            if -11 < maps[i][j] < 0: # 사람이면 이동해야지..
                for d in range(4):
                    x = i + direction[d][0]
                    y = j + direction[d][1]
                    # 움직인 칸은 현재 칸 보다 가까워야한다.
                    if abs(ex - i) + abs(ey - j) > abs(ex - x) + abs(ey - y):
                        if 0 <= x < N and 0 <= y < N and maps[x][y] <= 0:
                            """음수 주의"""
                            new_maps[i][j] -= maps[i][j] # 이동처리 (움직이기 전 자리는 나간만큼 채워준다)
                            move_cnt += maps[i][j]
                            if x == ex and y == ey: # 만약 이동한 곳이 출구라면
                                remain_man += maps[i][j] # 나간만큼 빼준다
                                # 좌표 갱신 없음. 나가서
                            else:
                                new_maps[x][y] += maps[i][j] # 이동처리 (새로운 좌표 갱신)
                            break
    maps = new_maps  # 복사
def find_square():
    # 가장 작은 사각형 찾기
    MIN = N-1
    for i in range(N):
        for j in range(N):
            if -11 < maps[i][j] < 0:
                MIN = min(MIN,max(abs(ex - i)+1,abs(ey - j)+1))
    # MIN size 의 정사각형 찾기
    start_x = N-1
    start_y = N-1
    man_list = []
    for i in range(N):
        for j in range(N):
            if -11 < maps[i][j] < 0:
                man_list.append([i,j])
    for sr in range(N-MIN+1):
        for sc in range(N-MIN+1):
            if (sr <= ex < sr + MIN and sc <= ey < sc + MIN):
                for x,y in man_list:
                    if (sr <= x < sr + MIN) and (sc <= y < sc + MIN):
                        start_x = sr
                        start_y = sc
                        return start_x, start_y, MIN
    return start_x,start_y,MIN

def rotate(sr,sc,size):
    global maps, ex,ey
    new_maps = [[0]*size for _ in range(size)] # 맵 복사
    for i in range(size):
        for j in range(size):
            new_maps[i][j] = maps[sr+size-1-j][sc+i]
            if new_maps[i][j] > 0:
                new_maps[i][j] -= 1

    for i in range(size):
        for j in range(size):
            maps[sr+i][sc+j] = new_maps[i][j]
            if maps[sr+i][sc+j] == -11:
                ex,ey = sr+i,sc+j

for k in range(M):
    x,y = man_point[k]
    maps[x-1][y-1] -= 1 # 참가자들 표시

maps[ex][ey] = -11 # 출구같은게 있으면 조건절 범위 확인 후 적용!

move_cnt = 0 # 모든 참가자들의 이동 거리함
while K > 0 and remain_man > 0 :
    move()
    if remain_man == 0:
        break
    # print('move',move_cnt)
    # for i in maps:
    #     print(i)
    sr,sc,size = find_square()
    # print(sr,sc,size)
    # for i in maps:
    #     print(i)
    rotate(sr,sc, size)

    K -= 1
print(-move_cnt)
print(ex+1,ey+1)

※ 알아야 할 것

- 동시에 움직이는 상황이면 뭐다? 복사 or 0으로 새로운 배열 만들기

- 회전하는 상황이면 뭐다? 복사 or 0으로 새로운 배열 만들기

728x90
반응형

'coding test - python > Code Tree' 카테고리의 다른 글

삼성 SW역량테스트 기출 / 2022 상반기 오전 1번 문제 술래잡기 / Python 파이썬  (8) 2024.10.12
삼성 SW역량테스트 기출 / 2022 하반기 오후 1번 문제 코드트리 빵 / Python 파이썬  (5) 2024.10.11
달팽이 너같은거...  (5) 2024.10.09
삼성 SW역량테스트 기출 / 2023 상반기 오전 1번 문제 포탑부수기 - BFS (조건문 확인 계속하기) / Python 파이썬  (13) 2024.10.08
삼성 SW역량테스트 기출 / 2024 상반기 오전 1번 문제 고대 문명 유적 탐사 - 얕은복사, 깊은 복사 / Python 파이썬  (8) 2024.10.05
'coding test - python/Code Tree' 카테고리의 다른 글
  • 삼성 SW역량테스트 기출 / 2022 상반기 오전 1번 문제 술래잡기 / Python 파이썬
  • 삼성 SW역량테스트 기출 / 2022 하반기 오후 1번 문제 코드트리 빵 / Python 파이썬
  • 달팽이 너같은거...
  • 삼성 SW역량테스트 기출 / 2023 상반기 오전 1번 문제 포탑부수기 - BFS (조건문 확인 계속하기) / Python 파이썬
sillon
sillon
꾸준해지려고 합니다..
    반응형
  • sillon
    sillon coding
    sillon
  • 전체
    오늘
    어제
    • menu (614)
      • notice (2)
      • python (68)
        • 자료구조 & 알고리즘 (23)
        • 라이브러리 (19)
        • 기초 (8)
        • 자동화 (14)
        • 보안 (1)
      • coding test - python (301)
        • Programmers (166)
        • 백준 (76)
        • Code Tree (22)
        • 기본기 문제 (37)
      • coding test - C++ (5)
        • Programmers (4)
        • 백준 (1)
        • 기본기문제 (0)
      • 공부정리 (5)
        • 신호처리 시스템 (0)
        • Deep learnig & Machine lear.. (41)
        • Data Science (18)
        • Computer Vision (17)
        • NLP (40)
        • Dacon (2)
        • 모두를 위한 딥러닝 (강의 정리) (4)
        • 모두의 딥러닝 (교재 정리) (9)
        • 통계 (2)
      • HCI (23)
        • Haptics (7)
        • Graphics (11)
        • Arduino (4)
      • Project (21)
        • Web Project (1)
        • App Project (1)
        • Paper Project (1)
        • 캡스톤디자인2 (17)
        • etc (1)
      • OS (10)
        • Ubuntu (9)
        • Rasberry pi (1)
      • App & Web (9)
        • Android (7)
        • javascript (2)
      • C++ (5)
        • 기초 (5)
      • Cloud & SERVER (8)
        • Git (2)
        • Docker (1)
        • DB (4)
      • Paper (7)
        • NLP Paper review (6)
      • 데이터 분석 (0)
        • GIS (0)
      • daily (2)
        • 대학원 준비 (0)
      • 영어공부 (6)
        • job interview (2)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    소수
    programmers
    Python
    백준
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.3
sillon
삼성 SW역량테스트 기출 / 2023 상반기 오후 1번 문제 메이즈러너 - 회전, BFS, 가장 작은 정사각형 찾고 회전 / Python 파이썬
상단으로

티스토리툴바