[와일트루] 9월 3-4주차: 0912-0925

최정윤·2023년 9월 25일
0

알고리즘

목록 보기
26/41
post-custom-banner

🫧 13565. 침투

문제

인제대학교 생화학연구실에 재직중인 석교수는 전류가 침투(percolate) 할 수 있는 섬유 물질을 개발하고 있다. 이 섬유 물질은 2차원 M × N 격자로 표현될 수 있다. 편의상 2차원 격자의 위쪽을 바깥쪽(outer side), 아래쪽을 안쪽(inner side)라고 생각하기로 한다. 또한 각 격자는 검은색 아니면 흰색인데, 검은색은 전류를 차단하는 물질임을 뜻하고 흰색은 전류가 통할 수 있는 물질임을 뜻한다. 전류는 섬유 물질의 가장 바깥쪽 흰색 격자들에 공급되고, 이후에는 상하좌우로 인접한 흰색 격자들로 전달될 수 있다.

김 교수가 개발한 섬유 물질을 나타내는 정보가 2차원 격자 형태로 주어질 때, 바깥쪽에서 흘려 준 전류가 안쪽까지 침투될 수 있는지 아닌지를 판단하는 프로그램을 작성하시오.

[(a) The current percolates.]

[(b) The current does not percolate.]

예를 들어, Figure 1(a) 에서는 바깥쪽에서 공급된 전류가 안쪽까지 침투하지만, Figure 1(b)에서는 그렇지 못한다.

입력

첫째 줄에는 격자의 크기를 나타내는 M (2 ≤ M ≤ 1,000) 과 N (2 ≤ N ≤ 1,000) 이 주어진다. M줄에 걸쳐서, N개의 0 또는 1 이 공백 없이 주어진다. 0은 전류가 잘 통하는 흰색, 1은 전류가 통하지 않는 검은색 격자임을 뜻한다.

출력

바깥에서 흘려준 전류가 안쪽까지 잘 전달되면 YES를 출력한다.

그렇지 않으면 NO를 출력한다.

예제 입력 1

5 6
010101
010000
011101
100011
001011

예제 출력 1

NO

예제 입력 2

8 8
11000111
01100000
00011001
11001000
10001001
10111100
01010000
00001011

예제 출력 2

YES

알고리즘 분류

  • 그래프 이론
  • 그래프 탐색
  • 너비 우선 탐색
  • 깊이 우선 탐색

코드 - python3 성공

import sys
from collections import deque

input = sys.stdin.readline

m, n = map(int, input().rstrip().split())
graph = [list(map(int, input().rstrip())) for _ in range(m)]
dx = [-1, 1, 0, 0]
dy = [0, 0, -1, 1]


def bfs(x, y):
    q = deque()
    q.append((x, y))
    graph[x][y] = 2  # 방문한 곳 2로 초기화

    while q:
        a, b = q.popleft()

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

            if 0 <= nx < m and 0 <= ny < n: # nx, ny가 내부 좌표일때
                if graph[nx][ny] == 0:  # 0은 흰색이므로 침투가능
                    graph[nx][ny] = 2 # 방문좌표를 방문표시해줌
                    q.append((nx, ny)) # 해당좌표 저장


for i in range(len(graph[0])):  # 위쪽 모든 좌표에서 침투시작
    bfs(0, i)

if graph[m - 1].count(2):  # 그래프 마지막 줄에 2가 있으면 침투 성공
    print("YES")
else:
    print("NO")

🫧 6064. 카잉 달력

문제

최근에 ICPC 탐사대는 남아메리카의 잉카 제국이 놀라운 문명을 지닌 카잉 제국을 토대로 하여 세워졌다는 사실을 발견했다. 카잉 제국의 백성들은 특이한 달력을 사용한 것으로 알려져 있다. 그들은 M과 N보다 작거나 같은 두 개의 자연수 x, y를 가지고 각 년도를 <x:y>와 같은 형식으로 표현하였다. 그들은 이 세상의 시초에 해당하는 첫 번째 해를 <1:1>로 표현하고, 두 번째 해를 <2:2>로 표현하였다. <x:y>의 다음 해를 표현한 것을 <x':y'>이라고 하자. 만일 x < M 이면 x' = x + 1이고, 그렇지 않으면 x' = 1이다. 같은 방식으로 만일 y < N이면 y' = y + 1이고, 그렇지 않으면 y' = 1이다. <M:N>은 그들 달력의 마지막 해로서, 이 해에 세상의 종말이 도래한다는 예언이 전해 온다.

예를 들어, M = 10 이고 N = 12라고 하자. 첫 번째 해는 <1:1>로 표현되고, 11번째 해는 <1:11>로 표현된다. <3:1>은 13번째 해를 나타내고, <10:12>는 마지막인 60번째 해를 나타낸다.

네 개의 정수 M, N, x와 y가 주어질 때, <M:N>이 카잉 달력의 마지막 해라고 하면 <x:y>는 몇 번째 해를 나타내는지 구하는 프로그램을 작성하라.

입력

입력 데이터는 표준 입력을 사용한다. 입력은 T개의 테스트 데이터로 구성된다. 입력의 첫 번째 줄에는 입력 데이터의 수를 나타내는 정수 T가 주어진다. 각 테스트 데이터는 한 줄로 구성된다. 각 줄에는 네 개의 정수 M, N, x와 y가 주어진다. (1 ≤ M, N ≤ 40,000, 1 ≤ x ≤ M, 1 ≤ y ≤ N) 여기서 <M:N>은 카잉 달력의 마지막 해를 나타낸다.

출력

출력은 표준 출력을 사용한다. 각 테스트 데이터에 대해, 정수 k를 한 줄에 출력한다. 여기서 k는 <x:y>가 k번째 해를 나타내는 것을 의미한다. 만일 <x:y>에 의해 표현되는 해가 없다면, 즉, <x:y>가 유효하지 않은 표현이면, -1을 출력한다.

예제 입력 1

3
10 12 3 9
10 12 7 2
13 11 5 6

예제 출력 1

33
-1
83

알고리즘 분류

  • 수학
  • 정수론
  • 중국인의 나머지 정리

풀이

  • 최소공배수

코드 - python3 성공

import sys
input = sys.stdin.readline

def calculate(m, n, x, y):
    k = x #k를 x로 초기화: k-x가 m의 배수여야 하기 때문
    while k <= m * n: #k의 범위는 m*n(카잉 달력의 총 년도 수 = m과 n의 최소공배수)을 넘을 수 없기 때문
        # x와 y가 각자의 주기(m과 n)에 맞게 증가하는 것
        if (k - x) % m == 0 and (k - y) % n == 0: #2개의 조건을 만족하는 k값을 찾는다.
            return k
        k += m # 처음에 k를 x로 설정했으므로 다음 가능한 후보는 x + m일 것이기 때문
    return -1

t = int(input())

for _ in range(t):
    m, n, x, y = map(int, input().split())

    print(calculate(m, n, x, y))

🫧 14232. 보석 도둑

문제

희대의 도둑 효빈이는 세계 최고의 보석가게 영선상에 잠입할 계획이다. 이 영선상은 최고의 보석가게답게 최고의 보안장치를 두고 있는데, 이 보안장치를 해제하지 않는다면 보석을 여러 개 훔쳐갈 시, 보석끼리 달라붙으며 무게가 모든 보석들의 곱으로 늘어난다.

효빈이는 이 보안장치를 해제할 수 없기 때문에, 차라리 곱해진 대로 최대한 많은 보석들을 가져오기로 계획했다. 효빈이는 한번에 k라는 무게를 들 수 있으므로, 딱 k만큼의 무게만큼의 보석을 가져오고 싶은데, 그 때 보석들의 최대 개수를 알고싶다.

영선상에는 세계 최고의 보석가게답게 모든 무게의 보석들이 매우 많이때문에, 훔쳐가는 보석이 부족할 일은 없다. 다만 모든 보석들은 무게가 1보다 크다.

효빈이는 이제 영선상에 잡입할 계획을 다 세웠다. 하지만 무슨 보석들을 훔쳐올지 결정하지 못하였는데, 효빈이를 대신하여 훔쳐올 보석들을 결정해주자.

입력

첫째 줄에는 효빈이가 들 수 있는 무게 k가 주어진다.(2≤k≤1012)

출력

첫째 줄에는 효빈이가 훔쳐올 보석의 개수를 출력하고, 다음 줄에는 훔쳐올 보석들의 무게를 오름차순으로 출력하시오.

예제 입력 1

15

예제 출력 1

2
3 5

알고리즘 분류

  • 수학
  • 정수론
  • 소수 판정
  • 에라토스테네스의 체

풀이

  • 소인수분해

코드 - python3 성공

import sys
from math import sqrt, ceil # 제곱근, 올림
input = sys.stdin.readline

k = int(input())
j = [] # 보석 무게 리스트

for i in range(2, ceil(sqrt(k)) + 1):
    while k % i == 0: # 나누어 떨어지는 k값 구하기
        j.append(i)
        k //= i # 해당 i 값으로 나눈 후 다시 순환

if k != 1: # 소인수분해 되지 않은 값이 있다면
    j.append(k) # 해당값 저장

print(len(j))
print(*j)

🫧 1107. 리모컨

문제

수빈이는 TV를 보고 있다. 수빈이는 채널을 돌리려고 했지만, 버튼을 너무 세게 누르는 바람에, 일부 숫자 버튼이 고장났다.

리모컨에는 버튼이 0부터 9까지 숫자, +와 -가 있다. +를 누르면 현재 보고있는 채널에서 +1된 채널로 이동하고, -를 누르면 -1된 채널로 이동한다. 채널 0에서 -를 누른 경우에는 채널이 변하지 않고, 채널은 무한대 만큼 있다.

수빈이가 지금 이동하려고 하는 채널은 N이다. 어떤 버튼이 고장났는지 주어졌을 때, 채널 N으로 이동하기 위해서 버튼을 최소 몇 번 눌러야하는지 구하는 프로그램을 작성하시오.

수빈이가 지금 보고 있는 채널은 100번이다.

입력

첫째 줄에 수빈이가 이동하려고 하는 채널 N (0 ≤ N ≤ 500,000)이 주어진다. 둘째 줄에는 고장난 버튼의 개수 M (0 ≤ M ≤ 10)이 주어진다. 고장난 버튼이 있는 경우에는 셋째 줄에는 고장난 버튼이 주어지며, 같은 버튼이 여러 번 주어지는 경우는 없다.

출력

첫째 줄에 채널 N으로 이동하기 위해 버튼을 최소 몇 번 눌러야 하는지를 출력한다.

예제 입력 1

5457
3
6 7 8

예제 출력 1

6

예제 입력 2

100
5
0 1 2 3 4

예제 출력 2

0

예제 입력 3

500000
8
0 2 3 4 6 7 8 9

예제 출력 3

11117

예제 입력 4

100
3
1 0 5

예제 출력 4

0

예제 입력 5

14124
0

예제 출력 5

5

예제 입력 6

1
9
1 2 3 4 5 6 7 8 9

예제 출력 6

2

예제 입력 7

80000
2
8 9

예제 출력 7

2228

알고리즘 분류

  • 브루트포스 알고리즘

코드

import sys
input = sys.stdin.readline

n = int(input())
m = int(input())
broken = list(map(int, input().split()))

# 현재 채널에서 + 혹은 -만 사용하여 이동하는 경우
min_count = abs(100 - n)

for nums in range(1000001):
    nums = str(nums)

    for j in range(len(nums)):
        # 각 숫자가 고장났는지 확인 후, 고장 났으면 break
        if int(nums[j]) in broken:
            break

        # 고장난 숫자 없이 마지막 자리까지 왔다면 min_count 비교 후 더 작은 값으로 업데이트
        elif j == len(nums) - 1:
            min_count = min(min_count, abs(int(nums) - n) + len(nums))

print(min_count)
profile
개발 기록장
post-custom-banner

0개의 댓글