반응형

문제 설명

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/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/18870

 

18870번: 좌표 압축

수직선 위에 N개의 좌표 X1, X2, ..., XN이 있다. 이 좌표에 좌표 압축을 적용하려고 한다. Xi를 좌표 압축한 결과 X'i의 값은 Xi > Xj를 만족하는 서로 다른 좌표의 개수와 같아야 한다. X1, X2, ..., XN에 좌

www.acmicpc.net

문제 설명

수직선 위에 N개의 좌표 X1, X2, ..., XN이 있다. 이 좌표에 좌표 압축을 적용하려고 한다.

Xi를 좌표 압축한 결과 X'i의 값은 Xi > Xj를 만족하는 서로 다른 좌표의 개수와 같아야 한다.

X1, X2, ..., XN에 좌표 압축을 적용한 결과 X'1, X'2, ..., X'N를 출력해보자.


풀이 과정

먼저, 좌표 압축이라는 것은 여러 곳에 흩뿌려진 좌표들을 연속된 수들로 모아 압축하는 것을 말한다.

예를 들어, 다음과 같은 좌표가 있다고 하자.

[1, 10, 10000, 1000000]

이렇게 네 점의 좌표가 있을 때, 좌표는 네 개 이지만 좌표값이 1부터 1,000,000 까지 있다.

하지만 이 좌표를 압축하여 순서대로 표현하면 [0, 1, 2, 3] 이 된다.

 

즉, 작은 값부터 시작해서 0부터 인덱스를 부여하는 방식이다.

1이 가장 작으므로 0이되고 10이 1, 10000이 2, 1000000이 3이 되는 것이다.

 

좌표압축을 위해 먼저 수들을 입력받은 후에,

정렬을 하기전에 앞서, 같은 수는 같은 좌표값을 가지므로 집합(Set)으로 중복값을 없애주자.

그리고 정렬을 해서 각 숫자들과 인덱스를 딕셔너리에 저장을 하면 된다.

 

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

import sys
n = int(input())

numbers = list(map(int, sys.stdin.readline().rstrip().split()))

numset = set(numbers)
a = list(numset)
a.sort()

numdict = {}
for i in range(len(a)):
    numdict[a[i]] = i

for i in numbers:
    print(numdict[i], end=' ')

https://github.com/HongEunho

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

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

반응형
반응형

문제 설명

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

 

2108번: 통계학

첫째 줄에 수의 개수 N(1 ≤ N ≤ 500,000)이 주어진다. 단, N은 홀수이다. 그 다음 N개의 줄에는 정수들이 주어진다. 입력되는 정수의 절댓값은 4,000을 넘지 않는다.

www.acmicpc.net

수를 처리하는 것은 통계학에서 상당히 중요한 일이다. 통계학에서 N개의 수를 대표하는 기본 통계값에는 다음과 같은 것들이 있다. 단, N은 홀수라고 가정하자.

  1. 산술평균 : N개의 수들의 합을 N으로 나눈 값
  2. 중앙값 : N개의 수들을 증가하는 순서로 나열했을 경우 그 중앙에 위치하는 값
  3. 최빈값 : N개의 수들 중 가장 많이 나타나는 값
  4. 범위 : N개의 수들 중 최댓값과 최솟값의 차이

N개의 수가 주어졌을 때, 네 가지 기본 통계값을 구하는 프로그램을 작성하시오.


풀이 과정

최빈값을 구하는 부분이 제일 까다로운 문제이다.

이 부분은 파이썬의 Counter를 이용하자.

 

Counter는 리스트의 각 숫자들의 등장횟수를 카운트하여 몇 회 등장했는지 딕셔너리로 표현한다.

그리고 Counter의 most_common(n)은 빈도수가 가장 많은 것 부터 n개의 수를 (숫자, 등장횟수)의 형태로 반환한다.

n을 생략한다면 리스트의 모든 수를 반환한다.

 

최빈값이 두 개 이상일 경우에는 두 번째로 작은 값을 출력하라고 했으므로

다음과 같이 알고리즘을 짰다.

tmp[0][1] == tmp[1][1] 이라면 최빈값 리스트의 첫 번째 수와 두 번째 수의 등장횟수가 같다는 것이므로

최빈값이 두 개 이상이 된다.

그래서 두 번째 값을 출력하면 된다.

 

그 외에는 tmp[0][0]을 출력하면 된다.

import math
from collections import Counter
n = int(input())

numList = []
for i in range(n):
    numList.append(int(input()))


print(round(sum(numList) / n))
numList.sort()
print(numList[n//2])
cnt = Counter(numList)
tmp = cnt.most_common()

if len(tmp) > 1:
    if tmp[0][1] == tmp[1][1]:
        print(tmp[1][0])
    else:
        print(tmp[0][0])
else:
    print(tmp[0][0])

print(max(numList) - min(numList))

https://github.com/HongEunho

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

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

반응형
반응형

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

 

1002번: 터렛

각 테스트 케이스마다 류재명이 있을 수 있는 위치의 수를 출력한다. 만약 류재명이 있을 수 있는 위치의 개수가 무한대일 경우에는 -1을 출력한다.

www.acmicpc.net

문제 설명

두 좌표 (x1, y1)와 (x2, y2)가 주어지고, 목표점과의 거리 r1, r2가 주어질 때

목표점이 존재할 수 있는 좌표의 수를 구하는 문제이다.


풀이 과정

이 문제는 고등학교 교과과정에서 배웠던 원의 방정식 중 두 원의 교점을 활용하는 문제이다.

먼저, 원이라는 것은 하나의 정점으로부터 같은 거리를 가지는 점들의 집합이므로

정점(x1, y1)로 부터 거리 r1을 가진 점들은 원으로 존재할 것이고

정점(x2, y2)로 부터 거리 r2을 가진 점들은 원으로 존재할 것이기 때문이다.

 

두 원은 다음과 같은 관계로 존재할 수 있다.

출처 : Primitive님 블로그

위의 경우들을 다음과 같이 코드로 표현하면 되는 문제이다.

import math
t = int(input())

for i in range(t):
    x1, y1, r1, x2, y2, r2 = map(int, input().split())
    dist = math.sqrt((x1 - x2)**2 + (y1-y2)**2)

    if x1 == x2 and y1 == y2:   # 두 원의 중심이 같을 때
        if r1 == r2:            # 반지름이 같으면 : 같은 원
            print(-1)
        else:
            print(0)            # 다르면 영원히 만나지 않음

    else:                       # 두 원의 중심이 다를 때
        if abs(r1-r2) == dist or r1 + r2 == dist: # 내접원 or 외접원
            print(1)
        elif abs(r1-r2) < dist < r1 + r2:   # 두 점에서 만날 때
            print(2)
        else:           # 만나지 않음
            print(0)

https://github.com/HongEunho

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

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

반응형

+ Recent posts