반응형

문제 설명

https://www.acmicpc.net/problem/21610

 

21610번: 마법사 상어와 비바라기

마법사 상어는 파이어볼, 토네이도, 파이어스톰, 물복사버그 마법을 할 수 있다. 오늘 새로 배운 마법은 비바라기이다. 비바라기를 시전하면 하늘에 비구름을 만들 수 있다. 오늘은 비바라기

www.acmicpc.net

문제에서 주어진 조건사항들을 그대로 구현하는 문제이다.

큰 제약사항이나 알고리즘이 따로 사용되지는 않으므로 순서에 맞게 그대로 구현만 잘 해주면 된다.


풀이 과정

문제에서 특별히 신경써주어야 하는 부분은, 조건5 부분이다.

 

먼저, 구름이 di 방향으로 si칸 이동한 후에 비를 뿌리고 구름은 사라진다.

이 때, 구름이 사라진 칸은 물복사 버그 후에 구름이 생길 수 없기 때문에 1로 표시해주어

해당 턴에 구름이 생길 수 없도록 해주었다.

 

그리고 그 칸에 영원히 구름이 생길 수 없는 것이 아니라,

해당 턴에만 생길 수 없기 때문에

raining 함수의 마지막 부분에 1로 표시해둔 칸을 다시 0으로 표시하여 구름이 생길 수 있도록 해주었다.

 

코드의 cloud는 현재 턴에서 처음의 구름 위치를 담은 큐이고

queue는 이 구름들을 이동시킨 후의 구름 위치이다.

from collections import deque

n, m = map(int, input().split())
board = []
rain = [[0] * n for _ in range(n)]
dx = [0, -1, -1, -1, 0, 1, 1, 1]
dy = [-1, -1, 0, 1, 1, 1, 0, -1]

for i in range(n):
    board.append(list(map(int, input().split())))

cloud = deque([(n - 1, 0), (n - 1, 1), (n - 2, 0), (n - 2, 1)])


def raining(dir, dist):
    queue = deque()
    while cloud:
        a, b = cloud.popleft()
        nx = (a + dx[dir] * dist) % n
        ny = (b + dy[dir] * dist) % n
        board[nx][ny] += 1
        rain[nx][ny] = 1  # 사라진 칸은 1 표시
        queue.append((nx, ny))
        
    while queue:
        a, b = queue.popleft()
        for i in range(1, 8, 2):
            nx = a + dx[i]
            ny = b + dy[i]
            if nx < 0 or nx >= n or ny < 0 or ny >= n:
                continue
            if board[nx][ny] > 0:
                board[a][b] += 1

    for i in range(n):
        for j in range(n):
            if rain[i][j] == 1:
                rain[i][j] = 0
                continue
            if board[i][j] >= 2:
                cloud.append((i, j))
                board[i][j] -= 2


for i in range(m):
    d, s = map(int, input().split())
    raining(d - 1, s)

answer = 0
for i in range(n):
    answer += sum(board[i])

print(answer)

https://github.com/HongEunho

전체 문제 & 코드는 위의 깃에 정리되어 있습니다.

팔로우 & 맞팔은 환영입니다 !

반응형
반응형

https://www.acmicpc.net/problem/14891

 

14891번: 톱니바퀴

총 8개의 톱니를 가지고 있는 톱니바퀴 4개가 아래 그림과 같이 일렬로 놓여져 있다. 또, 톱니는 N극 또는 S극 중 하나를 나타내고 있다. 톱니바퀴에는 번호가 매겨져 있는데, 가장 왼쪽 톱니바퀴

www.acmicpc.net

문제 설명

문제에서 주어진 4개의 톱니바퀴를 규칙에 맞게 회전시키는 문제이다.

별다른 알고리즘 없이 문제에서 주어진 사항을 순서대로 구현만 하면 되는 문제이다.


풀이 과정

이 문제는 별다른 알고리즘 없이 문제에서 주어진 사항을 그대로 구현만 하면 되는 문제이다.

12시 방향을 0인덱스로 시작하여 11시 방향을 7 인덱스로 번호를 붙이기 때문에

현재 톱니바퀴의 왼쪽을 검사할 때는 [i][6] == [i-1][2] 인지 검사하면 되고

오른쪽을 검사할 때는 [i][2] == [i+1][6] 인지 검사하면 된다.

 

0과 3번째 톱니바퀴는 각각 오른쪽과 왼쪽만 검사하면 되지만

1, 2번째 톱니바퀴는 오른쪽 왼쪽 모두 검사해야 하므로 이 부분을 고려하여 코드를 작성하면 된다.

 

그리고, 현재 오른쪽의 톱니바퀴가 회전해야 한다면 연쇄적으로 모든 오른쪽 톱니바퀴를 고려해주어야 하고

왼쪽도 마찬가지이다.

 

def turn(idx, dir):
    if dir == 1:  # 시계
        wheel[idx][0], wheel[idx][1], wheel[idx][2], wheel[idx][3], wheel[idx][4], wheel[idx][5], wheel[idx][6], \
        wheel[idx][7] = \
            wheel[idx][7], wheel[idx][0], wheel[idx][1], wheel[idx][2], wheel[idx][3], wheel[idx][4], wheel[idx][5], \
            wheel[idx][6]
    else:  # 반시계
        wheel[idx][0], wheel[idx][1], wheel[idx][2], wheel[idx][3], wheel[idx][4], wheel[idx][5], wheel[idx][6], \
        wheel[idx][7] = \
            wheel[idx][1], wheel[idx][2], wheel[idx][3], wheel[idx][4], wheel[idx][5], wheel[idx][6], wheel[idx][7], \
            wheel[idx][0]


def solve(idx, dir):
    if idx == 0:
        if wheel[0][2] == wheel[1][6]:
            turn(0, dir)  # 0번만 턴
        else:
            if wheel[1][2] == wheel[2][6]:  # 0, 1번 턴
                turn(0, dir)
                turn(1, -dir)
            else:
                if wheel[2][2] == wheel[3][6]:  # 0, 1, 2번 턴
                    turn(0, dir)
                    turn(1, -dir)
                    turn(2, dir)
                else:  # 모두 다르기 때문에 턴
                    turn(0, dir)
                    turn(1, -dir)
                    turn(2, dir)
                    turn(3, -dir)

    elif idx == 1:
        if wheel[1][2] == wheel[2][6]:  # 1, 2번 톱니 같을 때
            if wheel[1][6] == wheel[0][2]:  # 0, 1번 톱니도 같으면
                turn(1, dir)  # 1번만 회전
            else:  # 0,1 은 다르면
                turn(1, dir)
                turn(0, -dir)

        else:  # 1, 2번 톱니 다를 때
            if wheel[1][6] == wheel[0][2]:  # 0, 1번 톱니는 같다면
                if wheel[2][2] == wheel[3][6]:
                    turn(1, dir)
                    turn(2, -dir)
                else:
                    turn(1, dir)
                    turn(2, -dir)
                    turn(3, dir)
            else:  # 0, 1번 톱니도 다르면
                if wheel[2][2] == wheel[3][6]:  # 2, 3번 톱니는 같다면
                    turn(0, -dir)
                    turn(1, dir)
                    turn(2, -dir)
                else:
                    turn(0, -dir)
                    turn(1, dir)
                    turn(2, -dir)
                    turn(3, dir)

    elif idx == 2:
        if wheel[2][6] == wheel[1][2]:  # 1, 2번 톱니 같을 때
            if wheel[2][2] == wheel[3][6]:  # 2, 3번 톱니도 같으면
                turn(2, dir)  # 2번만 회전
            else:  # 2, 3은 다르면
                turn(2, dir)
                turn(3, -dir)

        else:  # 1, 2번 톱니 다를 때
            if wheel[3][6] == wheel[2][2]:  # 2, 3번 톱니는 같다면
                if wheel[0][2] == wheel[1][6]:
                    turn(2, dir)
                    turn(1, -dir)
                else:
                    turn(0, dir)
                    turn(1, -dir)
                    turn(2, dir)
            else:  # 2, 3번 톱니도 다르면
                if wheel[0][2] == wheel[1][6]:  # 0, 1번 톱니는 같다면
                    turn(1, -dir)
                    turn(2, dir)
                    turn(3, -dir)
                else:
                    turn(0, dir)
                    turn(1, -dir)
                    turn(2, dir)
                    turn(3, -dir)

    else:
        if wheel[3][6] == wheel[2][2]:
            turn(3, dir)
        else:
            if wheel[1][2] == wheel[2][6]:
                turn(3, dir)
                turn(2, -dir)
            else:
                if wheel[1][6] == wheel[0][2]:
                    turn(3, dir)
                    turn(2, -dir)
                    turn(1, dir)
                else:
                    turn(3, dir)
                    turn(2, -dir)
                    turn(1, dir)
                    turn(0, -dir)


wheel = []
for i in range(4):
    wheel.append(list(map(int, input())))

k = int(input())
for i in range(k):
    a, b = map(int, input().split())
    solve(a - 1, b)

answer = 0
for i in range(4):
    if wheel[i][0] == 0:
        answer += 0
    else:
        answer += 2 ** i

print(answer)

https://github.com/HongEunho

전체 문제 & 코드는 위의 깃에 정리되어 있습니다.

팔로우 & 맞팔은 환영입니다 !

반응형
반응형

https://www.acmicpc.net/problem/14503

 

14503번: 로봇 청소기

로봇 청소기가 주어졌을 때, 청소하는 영역의 개수를 구하는 프로그램을 작성하시오. 로봇 청소기가 있는 장소는 N×M 크기의 직사각형으로 나타낼 수 있으며, 1×1크기의 정사각형 칸으로 나누어

www.acmicpc.net

문제 설명

문제에서 주어진 것 처럼, 로봇 청소기가 빈공간을 돌아다니며 청소를 한다.

현재 방향을 기준으로 왼쪽 방향부터 탐색을 시작하며,

방향은 0 = 북 / 1 = 동 / 2 = 남 / 3 = 서쪽을 의미한다.

 

문제에서 주어진 조건과 상황들을 잘 고려하여 코드를 작성해보자.


풀이 과정

먼저 로봇 청소기의 초기 위치는 무조건 0이며 해당 칸을 청소하게 된다.

청소를 한 칸은 2로 변경하여 청소를 했음을 표시해주도록 하자.

그리고 이제 다음과 같이 시뮬레이션을 돌려주자.

 

왼쪽 방향칸을 청소 하지 않았다면(0 이라면)

현재 내 방향(d)를 왼쪽으로 전환하고 한 칸 전진한 후 그 칸을 청소한다.

이 때, 방향은 0 = 북 / 1 = 동 / 2 = 남 / 3 = 서 이므로

왼쪽로의 전환은 (d - 1)%4 를 통해 가능하다.

 

② 왼쪽 방향에 청소할 공간이 없다면(0 or 1 이라면)

현재 내 방향(d)를 왼쪽으로 전환하고 전진은 하지 않은 상태로 다시 ①단계로 돌아간다.

 

③ 네 방향 모두 청소가 되어있거나 벽인 경우(0 or 1이라면)

현재 내 방향(d)를 유지한 채로 한 칸 후진하여 ① 단계로 돌아간다.

 

④ 네 방향 모두 청소가 되어있거나 벽인 경우(0 or 1이라면)

뒤 쪽 방향이 벽(1)이라 후진조차 불가능하다면 작동을 멈춘다.

 

위 과정을 모두 거친 후, 로봇청소기가 청소한 칸의 갯수를 출력한다.

n, m = map(int, input().split())
r, c, d = map(int, input().split())
board = []
dx = [-1, 0, 1, 0]
dy = [0, 1, 0, -1]
answer = 1

for i in range(n):
    board.append(list(map(int, input().split())))


def dfs(x, y, depth):
    global answer, d
    if depth == 4:
        nx = x + dx[(d - 2) % 4]
        ny = y + dy[(d - 2) % 4]
        if board[nx][ny] == 2:
            dfs(nx, ny, 0)
        else:
            print(answer)
            exit(0)

    nx = x + dx[(d - 1) % 4]
    ny = y + dy[(d - 1) % 4]

    if board[nx][ny] == 0:
        board[nx][ny] = 2
        answer += 1
        d = (d - 1) % 4
        dfs(nx, ny, 0)

    elif board[nx][ny] == 1 or board[nx][ny] == 2:
        d = (d - 1) % 4
        dfs(x, y, depth + 1)


board[r][c] = 2
dfs(r, c, 0)

https://github.com/HongEunho

전체 문제 & 코드는 위의 깃에 정리되어 있습니다.

팔로우 & 맞팔은 환영입니다 !

반응형
반응형

https://www.acmicpc.net/problem/14502

 

14502번: 연구소

인체에 치명적인 바이러스를 연구하던 연구소에서 바이러스가 유출되었다. 다행히 바이러스는 아직 퍼지지 않았고, 바이러스의 확산을 막기 위해서 연구소에 벽을 세우려고 한다. 연구소는 크

www.acmicpc.net

문제 설명

N x M 크기로 구성된 연구소에 바이러스가 퍼졌다.

연구소의 각 칸은 0, 1, 2로 구성되어 있으며 0은 빈 칸, 1은 벽, 2은 바이러스 이다.

바이러스는 벽을 뚫고 확장할 수 없으며 상하좌우에 인접한 빈 칸으로만 확장이 가능하다.

위 그림과 같이 N x M 모양의 연구소(행렬)가 주어지며, 3개의 벽(1)을 세워야 한다.

3개의 벽을 세웠을 때, 안전영역의 크기(0의 개수)의 최댓값을 구하면 된다.


풀이 과정

바이러스는 '2' 이며 상하좌우의 인접한 빈칸(0)으로만 이동이 가능하기 때문에

먼저 '2'인 칸들을 모두 큐에 넣어준 후에,

BFS(너비우선탐색)을 통해 큐에서 하나씩 꺼내 확장시키는 방식으로 진행하면 된다.

 

2인 칸에서 시작하여 주변의 0인 칸들을 2로 만드는 방식이다.

 

이 때, 어디에 벽을 세워야 최댓값이 나올지는 알 수 없기 때문에 벽을 세울 수 있는 모든 경우의 수에 대해 수행해봐야 한다.

따라서, (1, 1) 칸 부터 (n, m)칸 까지 중 빈칸을 순서대로 하나씩 3개 선택하여

벽을 세우고 BFS를 수행한 후 벽을 지우고

그 다음칸에 대해 다시 벽을 세우고 BFS를 수행하고 벽을 지우는 방식을 반복해야 한다.

즉, 백트래킹 방식을 이용해 3개의 벽을 모든 칸에 세워본다.

 

이렇게 진행하면서 최댓값을 저장한 후, 모든 탐색이 끝난 후 최댓값을 출력하면 된다.

 

이를 파이썬으로 나타낸 코드는 다음과 같다.

from collections import deque
import copy

def bfs():
    queue = deque()
    tmp_graph = copy.deepcopy(graph)
    for i in range(n):
        for j in range(m):
            if tmp_graph[i][j] == 2:
                queue.append((i, j))

    while queue:
        x, y = queue.popleft()

        for i in range(4):
            nx = x + dx[i]
            ny = y + dy[i]

            if nx < 0 or nx >= n or ny < 0 or ny >= m:
                continue
            if tmp_graph[nx][ny] == 0:
                tmp_graph[nx][ny] = 2
                queue.append((nx, ny))

    global answer
    cnt = 0

    for i in range(n):
        cnt += tmp_graph[i].count(0)

    answer = max(answer, cnt)


def makeWall(cnt):
    if cnt == 3:
        bfs()
        return

    for i in range(n):
        for j in range(m):
            if graph[i][j] == 0:
                graph[i][j] = 1
                makeWall(cnt+1)
                graph[i][j] = 0

n, m = map(int, input().split())
graph = []
dx = [0, 0, 1, -1]
dy = [1, -1, 0, 0]

for i in range(n):
    graph.append(list(map(int, input().split())))

answer = 0
makeWall(0)
print(answer)

https://github.com/HongEunho

전체 문제 & 코드는 위의 깃에 정리되어 있습니다.

팔로우 & 맞팔은 환영입니다 !

반응형
반응형

https://www.acmicpc.net/problem/14500

 

14500번: 테트로미노

폴리오미노란 크기가 1×1인 정사각형을 여러 개 이어서 붙인 도형이며, 다음과 같은 조건을 만족해야 한다. 정사각형은 서로 겹치면 안 된다. 도형은 모두 연결되어 있어야 한다. 정사각형의 변

www.acmicpc.net

문제 설명

폴리오미노란 크기가 1×1인 정사각형을 여러 개 이어서 붙인 도형이며, 다음과 같은 조건을 만족해야 한다.

  • 정사각형은 서로 겹치면 안 된다.
  • 도형은 모두 연결되어 있어야 한다.
  • 정사각형의 변끼리 연결되어 있어야 한다. 즉, 꼭짓점과 꼭짓점만 맞닿아 있으면 안 된다.

정사각형 4개를 이어 붙인 폴리오미노는 테트로미노라고 하며, 다음과 같은 5가지가 있다.

아름이는 크기가 N×M인 종이 위에 테트로미노 하나를 놓으려고 한다. 종이는 1×1 크기의 칸으로 나누어져 있으며, 각각의 칸에는 정수가 하나 쓰여 있다.

테트로미노 하나를 적절히 놓아서 테트로미노가 놓인 칸에 쓰여 있는 수들의 합을 최대로 하는 프로그램을 작성하시오.

테트로미노는 반드시 한 정사각형이 정확히 하나의 칸을 포함하도록 놓아야 하며, 회전이나 대칭을 시켜도 된다.


풀이 과정

이 문제는 푸는 방법이 다양하다.

DFS를 이용해 푸는 방법도 있고, 직접 테트리스 모형을 모두 고려하여 하나하나 확인해주는 방법도 있다.

 

DFS를 이용한 풀이는 깔끔하다는 장점이 있지만 시간이 좀 더 오래걸린다는 단점이 있고

직접 테트리스 모형을 만드는 풀이는 시간이 빠르다는 장점이 있지만, 구현이 조금 지저분하다는 단점이 있다.

 

시간을 고려한다면 직접 만드는 풀이가 좋을 것이며,

깔끔한 풀이를 고려한다면 DFS 풀이가 좋을 것 같다.

 

그래서 두 방법 모두 풀어보았다.

 

① 먼저 DFS를 이용한 풀이는 백트래킹을 이용해 맵의 처음부터 끝칸까지 모든 칸에 대해 DFS를 수행한다.

한 칸에서 DFS를 수행하게 되면 모든 테트리스 모형을 확인할 수가 있다.

예를 들어, 쭉 오른쪽으로 간다면 ㅡ 모양이 될 것이고

오른쪽으로 갔다 아래로 갔다 왼쪽으로 가면 ㅁ 모양이 완성될 것이다.

 

하지만 ㅗ 모양이 DFS로 완성할 수 없기 때문에

depth = 1일 때, 즉 2칸까지 완성했을 때 칸을 다음칸으로 옮기지 않은 그대로인 상태에서

DFS를 수행함으로써 ㅗ 모양을 만들 수 있다.

 

1번 풀이를 이용한 코드는 다음과 같다.

n, m = map(int, input().split())
board = []
visited = [[False] * m for _ in range(n)]

dx = [0, 0, 1, -1]
dy = [1, -1, 0, 0]

for i in range(n):
    board.append(list(map(int, input().split())))

answer = 0

def dfs(x, y, mysum, depth):
    global answer

    if depth == 3:
        answer = max(answer, mysum)
        return
    else:
        for i in range(4):
            nx = x + dx[i]
            ny = y + dy[i]
            if nx < 0 or nx >= n or ny < 0 or ny >= m or visited[nx][ny]:
                continue

            if depth == 1:  # ㅗ 모양은 DFS로 만들 수 없으므로 예외처리
                visited[nx][ny] = True
                dfs(x, y, mysum + board[nx][ny], depth + 1)
                visited[nx][ny] = False

            visited[nx][ny] = True
            dfs(nx, ny, mysum + board[nx][ny], depth + 1)
            visited[nx][ny] = False


for i in range(n):
    for j in range(m):
        visited[i][j] = True
        dfs(i, j, board[i][j], 0)
        visited[i][j] = False

print(answer)

 

② 테트리스 모형을 모두 배열로 만들어서 비교한다.

첫 칸부터 끝칸까지 모든 칸에 대해 테트리스 모형을 대입하여 최댓값을 비교해나가는 방식이다.

n, m = map(int, input().split())
board = []
for i in range(n):
    board.append(list(map(int, input().split())))

tetris = [
    [(0, 0), (0, 1), (1, 0), (1, 1)], # ㅡ
    [(0, 0), (0, 1), (0, 2), (0, 3)], # ㅣ
    [(0, 0), (1, 0), (2, 0), (3, 0)], # ㅁ
    [(0, 0), (1, 0), (1, 1), (2, 1)], # h
    [(1, 0), (0, 1), (1, 1), (2, 0)], # h 회전
    [(1, 0), (1, 1), (0, 1), (0, 2)], # ...
    [(0, 0), (0, 1), (1, 1), (1, 2)],
    [(0, 0), (1, 0), (2, 0), (2, 1)], # L
    [(0, 1), (1, 1), (2, 0), (2, 1)], # ...
    [(0, 0), (0, 1), (1, 0), (2, 0)],
    [(0, 0), (0, 1), (1, 1), (2, 1)],
    [(1, 0), (0, 1), (1, 1), (1, 2)],
    [(0, 0), (0, 1), (0, 2), (1, 1)],
    [(0, 0), (1, 0), (1, 1), (1, 2)],
    [(1, 0), (1, 1), (1, 2), (0, 2)],
    [(0, 0), (0, 1), (0, 2), (1, 0)],
    [(0, 0), (0, 1), (0, 2), (1, 2)],
    [(0, 0), (1, 0), (1, 1), (2, 0)],
    [(1, 0), (0, 1), (1, 1), (2, 1)] # ㅓ
]

def solution(x, y):
    global answer
    for i in range(19):
        tmp = 0
        for j in range(4):
            nx = x + tetris[i][j][0]
            ny = y + tetris[i][j][1]

            if nx < 0 or nx >= n or ny < 0 or ny >= m:
                break

            tmp += board[nx][ny]

        answer = max(answer, tmp)

answer = 0
for i in range(n):
    for j in range(m):
        solution(i, j)

print(answer)

 

③ 마찬가지로 모든 테트리스칸에 대해 수행하는 방법이지만

배열에 모두 기입하는 것이 아닌 함수로 하나씩 만들어 대입하는 방법이다.

 

수행시간은 이 풀이가 가장 짧았다.

하지만 구현해야 하는 코드의 길이가 상당히 긴 단점이 있다.

n, m = map(int,input().split())
graph = []
ans = 0

def shape1(i, j): # ㅡ
    if j+3 >= m:
        return 0
    return graph[i][j] + graph[i][j+1] + graph[i][j+2] + graph[i][j+3]

def shape2(i, j): # ㅣ
    if i+3 >= n:
        return 0
    return graph[i][j] + graph[i+1][j] + graph[i+2][j] + graph[i+3][j]

def shape3(i, j): # L모양
    if i+2 >= n or j+1 >= m:
        return 0
    return graph[i][j] + graph[i+1][j] + graph[i+2][j] + graph[i+2][j+1]

def shape4(i, j): # L모양 대칭
    if i+2 >= n or j-1 < 0:
        return 0
    return graph[i][j] + graph[i+1][j] + graph[i+2][j] + graph[i+2][j-1]

def shape5(i, j): # L모양 시계방향 회전
    if i-1 < 0 or j+2 >= m:
        return 0
    return graph[i][j] + graph[i-1][j] + graph[i-1][j+1] + graph[i-1][j+2]

def shape6(i, j): # L대칭 시계방향 회전
    if i+1 >= n or j+2 >=m:
        return 0
    return graph[i][j] + graph[i+1][j] + graph[i+1][j+1] + graph[i+1][j+2]

def shape7(i, j): # L 시계방향 회전x2
    if i+2 >= n or j+1 >= m:
        return 0
    return graph[i][j] + graph[i][j+1] + graph[i+1][j+1] + graph[i+2][j+1]

def shape8(i, j): # L대칭 시계방향 회전x2
    if i+2 >= n or j+1 >= m:
        return 0
    return graph[i][j] + graph[i][j+1] + graph[i+1][j] + graph[i+2][j]

def shape9(i, j): # L 시계방향 회전x3
    if i-1 < 0 or j+2 >= m:
        return 0
    return graph[i][j] + graph[i][j+1] + graph[i][j+2] + graph[i-1][j+2]

def shape10(i, j): # L대칭 시계방향 회전x3
    if i+1 >= n or j+2 >= m:
        return 0
    return graph[i][j] + graph[i][j+1] + graph[i][j+2] + graph[i+1][j+2]

def shape11(i, j): # ㅁ모양
    if i+1 >= n or j+1 >= m:
        return 0
    return graph[i][j] + graph[i][j+1] + graph[i+1][j] + graph[i+1][j+1]

def shape12(i, j): # 번개모양
    if i+2 >= n or j+1 >= m:
        return 0
    return graph[i][j] + graph[i+1][j] + graph[i+1][j+1] + graph[i+2][j+1]

def shape13(i, j): # 번개모양 회전
    if i-1 < 0 or j+2 >= m:
        return 0
    return graph[i][j] + graph[i][j+1] + graph[i-1][j+1] + graph[i-1][j+2]

def shape14(i, j): #번개모양 대칭
    if i+2 >= n or j-1 < 0:
        return 0
    return graph[i][j] + graph[i+1][j] + graph[i+1][j-1] + graph[i+2][j-1]

def shape15(i, j): #번개모양 대칭 회전
    if i+1 >= n or j+2 >= m:
        return 0
    return graph[i][j] + graph[i][j+1] + graph[i+1][j+1] + graph[i+1][j+2]

def shape16(i, j): #ㅗ모양
    if i-1 < 0 or j+2 >= m:
        return 0
    return graph[i][j] + graph[i][j+1] + graph[i-1][j+1] + graph[i][j+2]

def shape17(i, j): #ㅗ모양 회전
    if i+2 >= n or j+1 >= m:
        return 0
    return graph[i][j] + graph[i+1][j] + graph[i+1][j+1] + graph[i+2][j]

def shape18(i, j): #ㅗ모양 회전x2
    if i+1 >= n or j+2 >= m:
        return 0
    return graph[i][j] + graph[i][j+1] + graph[i+1][j+1] + graph[i][j+2]

def shape19(i, j): #ㅗ모양 회전x3
    if i+2 >= n or j-1 < 0:
        return 0
    return graph[i][j] + graph[i+1][j] + graph[i+1][j-1] + graph[i+2][j]


for i in range(n):
    graph.append(list(map(int,input().split())))

for i in range(n):
    for j in range(m):
        ans = max(ans, shape1(i,j), shape2(i,j), shape3(i,j), shape4(i,j), shape5(i,j), shape6(i,j), shape7(i,j), shape8(i,j), shape9(i,j),
                  shape10(i,j), shape11(i,j), shape12(i,j), shape13(i,j), shape14(i,j), shape15(i,j), shape16(i,j), shape17(i,j), shape18(i,j), shape19(i,j))

print(ans)

https://github.com/HongEunho

전체 문제 & 코드는 위의 깃에 정리되어 있습니다.

팔로우 & 맞팔은 환영입니다 !

반응형
반응형

https://www.acmicpc.net/problem/14499

 

14499번: 주사위 굴리기

첫째 줄에 지도의 세로 크기 N, 가로 크기 M (1 ≤ N, M ≤ 20), 주사위를 놓은 곳의 좌표 x y(0 ≤ x ≤ N-1, 0 ≤ y ≤ M-1), 그리고 명령의 개수 K (1 ≤ K ≤ 1,000)가 주어진다. 둘째 줄부터 N개의 줄에 지도

www.acmicpc.net

문제 설명

문제에서 맵이 주어지고 맵의 첫 칸(0, 0)에 주사위를 놓는다.

그리고 주사위를 상, 하, 좌, 우 로 굴리게 되는데 주사위와 바닥에 닿는 면은 맵의 숫자로 복사가 된다.

그리고 주사위를 굴렸을 때 주사위 위쪽면의 숫자를 출력해야 한다.

 

따라서, 주사위 전개도를 생각하며 풀어야 하는 문제이다.


풀이 과정

이 문제를 풀기 위해 주사위 전개도를 직접 그려보면서 생각을 했다.

문제에서 주어진 주사위 전개도를 보면 다음과 같이 생겼는데

주사위 전개도

1을 위쪽으로 6을 아래쪽으로 접게되면 다음과 같은 주사위가 탄생한다.

그리고 이 주사위를 상, 하, 좌, 우로 굴렸을 때의 모양을 생각해야 한다.

대표적으로, 좌 로 굴렸을 때의 주사위는 다음과 같다.

좌로 굴린 주사위

이 때 주사위가 어떻게 변했는지 보자.

인덱스 0부터 5까지 각각의 인덱스가 위쪽, 뒤쪽, 오른쪽, 왼쪽, 앞쪽, 바닥 이라고 했을 때

[1, 2, 3, 4, 5, 6] => [3, 2, 6, 1, 5, 4] 로 변했음을 알 수 있다.

 

마찬가지로 다른 방향으로 굴렸을 때에 대해서도 어떻게 변했는지를 알면 이 문제를 다 풀었다고 볼 수 있다.

 

이러한 규칙을 turn함수에 정의를 해놓고

굴려야 하는 타이밍에 함수를 실행시키면 된다.

 

나머지부분은 문제에서 주어진 대로 구현만 하면 된다.

이를 파이썬으로 나타낸 코드는 다음과 같다.

n, m, x, y, k = map(int, input().split())

board = []
dx = [0, 0, -1, 1]
dy = [1, -1, 0, 0]
dice = [0, 0, 0, 0, 0, 0]

def turn(dir):
    a, b, c, d, e, f = dice[0], dice[1], dice[2], dice[3], dice[4], dice[5]
    if dir == 1: #동
        dice[0], dice[1], dice[2], dice[3], dice[4], dice[5] = d, b, a, f, e, c

    elif dir == 2: #서
        dice[0], dice[1], dice[2], dice[3], dice[4], dice[5] = c, b, f, a, e, d

    elif dir == 3: #북
        dice[0], dice[1], dice[2], dice[3], dice[4], dice[5] = e, a, c, d, f, b

    else:
        dice[0], dice[1], dice[2], dice[3], dice[4], dice[5] = b, f, c, d, a, e

for i in range(n):
    board.append(list(map(int, input().split())))

comm = list(map(int, input().split()))

nx, ny = x, y
for i in comm:
    nx += dx[i-1]
    ny += dy[i-1]

    if nx < 0 or nx >= n or ny < 0 or ny >= m:
        nx -= dx[i-1]
        ny -= dy[i-1]
        continue
    turn(i)
    if board[nx][ny] == 0:
        board[nx][ny] = dice[-1]
    else:
        dice[-1] = board[nx][ny]
        board[nx][ny] = 0

    print(dice[0])

https://github.com/HongEunho

전체 문제 & 코드는 위의 깃에 정리되어 있습니다.

팔로우 & 맞팔은 환영입니다 !

반응형
반응형

https://www.acmicpc.net/problem/3190

 

3190번: 뱀

 'Dummy' 라는 도스게임이 있다. 이 게임에는 뱀이 나와서 기어다니는데, 사과를 먹으면 뱀 길이가 늘어난다. 뱀이 이리저리 기어다니다가 벽 또는 자기자신의 몸과 부딪히면 게임이 끝난다. 게임

www.acmicpc.net

문제 설명

뱀 꼬리물기 문제이다. 뱀이 사과를 먹으면 점점 꼬리를 늘려가게 되며

뱀의 머리가 꼬리에 닿거나 벽에 닿으면 끝나는 게임이다.

 

뱀의 꼬리를 이동시키는 부분을 로 구현하는 부분이 핵심이다.


풀이 과정

이 문제는 를 이용한 구현 문제로 다음과 같이 접근하였다.

 

① 먼저 그래프(맵)을 모두 0으로 채워준다.

② 사과 위치는 모두 2로 채워준다.

③ 앞으로 뱀이 차지하고 있는 부분은 1로 채워줄 것이다.

④ 뱀이 이동할 때 마다 머리와 꼬리는 한 칸씩 전진한다. (즉, 몸의 길이는 그대로이다.)

⑤ 이동했을 때 사과를 먹으면 머리는 전진하지만 꼬리는 그대로이다. (즉, 몸의 길이가 한 칸 늘어난다.)

⑥ 방향 전환을 해야 하는 타이밍에 맞춰 L이면 왼쪽, D이면 오른쪽으로 방향전환을 한다.

 

이렇게 무엇을 구현해야 할 지를 정리한 후에 이를 하나씩 차례차례 구현해주면 된다.

①②③ 은 그대로 구현을 하면 되기 때문에 따로 설명은 하지 않고

 

④의 경우에는 처음 시작 할 때, [0, 0]을 큐에 넣어 몸길이 1 뱀의 초기 위치 상태를 저장하고,

오른쪽으로 한 칸 이동하여 [0, 0]을 큐에서 pop하고

[0, 1]을 큐에 push하여 뱀의 위치 상태를 변경한다.

 

이런 식으로 뱀을 전진시키면 된다. ( 큐를 뱀의 몸을 나타낸다고 생각하면 된다. )

 

⑤의 경우는 graph[x][y] = 2일 때 이다. 머리만 전진하면 되므로 큐에서 pop을 하지 않고,

큐에 현재 머리 위치만 push함으로써 뱀의 몸 길이를 늘려준다.

 

⑥의 경우에는 현재 시간이 방향전환을 해야 하는 시간이면, 입력한 방향에 맞게 전환을 해주면 된다.

(딕셔너리를 이용해 시간을 키값으로, 방향을 밸류값으로 입력받았다.)

 

이를 코드로 나타내면 다음과 같다.

from collections import deque

n = int(input())
k = int(input())

graph = [[0] * n for _ in range(n)]
dx = [0, 1, 0, -1]
dy = [1, 0, -1, 0]

for i in range(k):
    a, b = map(int, input().split())
    graph[a - 1][b - 1] = 2

l = int(input())
dirDict = dict()
queue = deque()
queue.append((0, 0))

for i in range(l):
    x, c = input().split()
    dirDict[int(x)] = c

x, y = 0, 0
graph[x][y] = 1
cnt = 0
direction = 0

def turn(alpha):
    global direction
    if alpha == 'L':
        direction = (direction - 1) % 4
    else:
        direction = (direction + 1) % 4


while True:
    cnt += 1
    x += dx[direction]
    y += dy[direction]

    if x < 0 or x >= n or y < 0 or y >= n:
        break

    if graph[x][y] == 2:
        graph[x][y] = 1
        queue.append((x, y))
        if cnt in dirDict:
            turn(dirDict[cnt])

    elif graph[x][y] == 0:
        graph[x][y] = 1
        queue.append((x, y))
        tx, ty = queue.popleft()
        graph[tx][ty] = 0
        if cnt in dirDict:
            turn(dirDict[cnt])

    else:
        break

print(cnt)

https://github.com/HongEunho

전체 문제 & 코드는 위의 깃에 정리되어 있습니다.

팔로우 & 맞팔은 환영입니다 !

반응형
반응형

https://www.acmicpc.net/problem/12100

 

12100번: 2048 (Easy)

첫째 줄에 보드의 크기 N (1 ≤ N ≤ 20)이 주어진다. 둘째 줄부터 N개의 줄에는 게임판의 초기 상태가 주어진다. 0은 빈 칸을 나타내며, 이외의 값은 모두 블록을 나타낸다. 블록에 쓰여 있는 수는 2

www.acmicpc.net

문제 설명

문제에서 주어진 2048 게임을 구현하는 문제이다.

평소의 2048 게임과는 다르게 이동시 새 블록이 추가되지는 않으며

5번 움직였을 때 맵 내의 최대값을 출력하면 된다.


풀이 과정

백트래킹을 이용해 모든 경우의 수에 대해 확인을 해야 하는 브루트포스 문제이다.

 

움직일 수 있는 방향은 동, 서, 남, 북 4가지 이다.

만약, 동쪽으로 움직인다면 모든 행에 대해 n - 1칸부터 0번째 칸까지 동쪽으로 움직이는 것을 구현한다.

 

현재 움직이려는 블록의 동쪽 마지노선의 블록이 현재 블록과 같은 수라면

수를 더해준 후 마지노선 칸에 그 수를 넣어주고

현재 블록은 0으로 만들어 다음 블록들이 이동할 수 있도록 만든다.

( 0 0 2 2 = > 0 0 0 4 )

 

마지노선 블록이 0이라면 그 칸을 현재 블록의 숫자로 대체한 후

현재 블록을 0으로 만든다.

 

마지노선이 현재 블록과 같은 수가 아니라면, 합칠 수가 없기 때문에 마지노선을 하나 당긴다.

 

여기서 말하는 마지노선이란, 처음에는 동쪽 가장 끝이 될 것이며

동쪽 가장 끝이 이미 계산이 된 상태라면 -1씩 해주어 마지노선을 하나씩 줄여주는 것을 말한다.

 

그리고, 동쪽으로 움직인 경우를 만든 후에

서쪽으로 움직일 때는 동쪽으로 움직인 게임판을 이어서 이용하는 것이 아니라

동쪽으로 움직이기 전의 게임판을 서쪽으로 움직여야 하기 때문에

깊은복사(DeepCopy)를 통해 기존 맵을 복사해둔 후에 그 맵을 이동하도록 한다.

 

이를 코드로 구현하면 다음과 같다.

from copy import deepcopy

n = int(input())

graph = []
for i in range(n):
    graph.append(list(map(int, input().split())))

def move(board, dir):
    if dir == 0:  # 동쪽
        for i in range(n):
            top = n - 1
            for j in range(n - 2, -1, -1):
                if board[i][j]:
                    tmp = board[i][j]
                    board[i][j] = 0
                    if board[i][top] == 0:
                        board[i][top] = tmp
                    elif board[i][top] == tmp:
                        board[i][top] = tmp * 2
                        top -= 1
                    else:
                        top -= 1
                        board[i][top] = tmp

    elif dir == 1:  # 서쪽
        for i in range(n):
            top = 0
            for j in range(1, n):
                if board[i][j]:
                    tmp = board[i][j]
                    board[i][j] = 0
                    if board[i][top] == 0:
                        board[i][top] = tmp
                    elif board[i][top] == tmp:
                        board[i][top] = tmp * 2
                        top += 1
                    else:
                        top += 1
                        board[i][top] = tmp

    elif dir == 2:  # 남쪽
        for j in range(n):
            top = n - 1
            for i in range(n - 2, -1, -1):
                if board[i][j]:
                    tmp = board[i][j]
                    board[i][j] = 0
                    if board[top][j] == 0:
                        board[top][j] = tmp
                    elif board[top][j] == tmp:
                        board[top][j] = tmp * 2
                        top -= 1
                    else:
                        top -= 1
                        board[top][j] = tmp

    else:
        for j in range(n):
            top = 0
            for i in range(1, n):
                if board[i][j]:
                    tmp = board[i][j]
                    board[i][j] = 0
                    if board[top][j] == 0:
                        board[top][j] = tmp
                    elif board[top][j] == tmp:
                        board[top][j] = tmp * 2
                        top += 1
                    else:
                        top += 1
                        board[top][j] = tmp

    return board


def dfs(board, cnt):
    global ans
    if cnt == 5:
        for i in range(n):
            for j in range(n):
                ans = max(ans, board[i][j])
        return

    for i in range(4):
        tmp_board = move(deepcopy(board), i)
        dfs(tmp_board, cnt + 1)

ans = 0
dfs(graph, 0)
print(ans)

https://github.com/HongEunho

전체 문제 & 코드는 위의 깃에 정리되어 있습니다.

팔로우 & 맞팔은 환영입니다 !

반응형

+ Recent posts