Now Loading ...
-
-
버스 노선 개편하기
출처 : 버스 노선 개편하기
Solution
Python
import sys
input = sys.stdin.readline
N = int(input())
shuttles = []
for i in range(N):
S, E, C = map(int, input().split())
shuttles.append([S, E, C])
shuttles.sort()
answer = []
route = shuttles[0]
for i in range(1, len(shuttles)):
if route[1] >= shuttles[i][0]:
route = [route[0], max(route[1], shuttles[i][1]), min(route[2], shuttles[i][2])]
else:
answer.append(route)
route = shuttles[i]
answer.append(route)
print(len(answer))
for shuttle in answer:
print(*shuttle)
문제
서강 나라에서는 일직선 도로를 따라 $N$개의 버스 노선을 운영 중이다. 필요할 때마다 노선을 새로 만든 탓에 겹치거나 중복되는 노선이 많다. 복잡한 버스 노선에 지친 시민들을 위해 버스 노선을 개편하기로 했다.
각 버스 노선은 세 정수 $S$, $E$, $C$로 나타낼 수 있으며, 구간 $[S,E]$를 요금 $C$로 운행한다는 뜻이다. 어떤 두 버스 노선의 구간이 한 점 이상에서 겹친다면, 두 구간을 합친 새 노선으로 대체한다. 이때 요금은 더 낮은 금액의 요금을 따르기로 했다. 버스 노선 개편은 구간이 겹치는 버스 노선이 없을 때까지 진행한다.
그림 D.1: 개편 전과 개편 후의 버스 노선도
버스 노선들의 정보가 주어지면, 개편이 끝난 후 버스 노선의 정보를 출력하는 프로그램을 작성하자.
입력
첫 번째 줄에 버스 노선의 수 $N$이 주어진다. ($1 \le N \le 200\,000$)
두 번째 줄부터 $N$개의 줄에 각 버스 노선을 나타내는 세 정수 $S$, $E$, $C$가 주어진다. ($0 \le S \lt E \le 10^9$, $1 \le C \le 10^9$)
출력
첫 번째 줄에 개편이 끝난 후의 버스 노선의 수 $K$를 출력한다.
두 번째 줄부터 $K$개의 줄에 개편 후 각 버스 노선의 $S$, $E$, $C$를 $S$가 작은 순서대로 출력한다.
제한
예제 입력 1
복사
6
1 4 4
6 9 5
7 9 6
2 5 7
0 2 10
9 10 10
예제 출력 1
복사
2
0 5 4
6 10 5
예제 입력 2
복사
5
1 2 4
3 7 3
8 9 5
10 14 10
17 18 3
예제 출력 2
복사
5
1 2 4
3 7 3
8 9 5
10 14 10
17 18 3
힌트
-
시험 감독
출처 : 시험 감독
Solution
Python
import sys
input = sys.stdin.readline
N = int(input())
A = list(map(int, input().split()))
B, C = map(int, input().split())
sum = 0
for i in range(N):
s_num = A[i] - B
sum += 1
if s_num > 0:
sum += int(s_num/C)
if s_num%C > 0:
sum += 1
print(sum)
문제
총 N개의 시험장이 있고, 각각의 시험장마다 응시자들이 있다. i번 시험장에 있는 응시자의 수는 Ai명이다.
감독관은 총감독관과 부감독관으로 두 종류가 있다. 총감독관은 한 시험장에서 감시할 수 있는 응시자의 수가 B명이고, 부감독관은 한 시험장에서 감시할 수 있는 응시자의 수가 C명이다.
각각의 시험장에 총감독관은 오직 1명만 있어야 하고, 부감독관은 여러 명 있어도 된다.
각 시험장마다 응시생들을 모두 감시해야 한다. 이때, 필요한 감독관 수의 최솟값을 구하는 프로그램을 작성하시오.
입력
첫째 줄에 시험장의 개수 N(1 ≤ N ≤ 1,000,000)이 주어진다.
둘째 줄에는 각 시험장에 있는 응시자의 수 Ai (1 ≤ Ai ≤ 1,000,000)가 주어진다.
셋째 줄에는 B와 C가 주어진다. (1 ≤ B, C ≤ 1,000,000)
출력
각 시험장마다 응시생을 모두 감독하기 위해 필요한 감독관의 최소 수를 출력한다.
제한
예제 입력 1
복사
1
1
1 1
예제 출력 1
복사
1
예제 입력 2
복사
3
3 4 5
2 2
예제 출력 2
복사
7
예제 입력 3
복사
5
1000000 1000000 1000000 1000000 1000000
5 7
예제 출력 3
복사
714290
예제 입력 4
복사
5
10 9 10 9 10
7 20
예제 출력 4
복사
10
예제 입력 5
복사
5
10 9 10 9 10
7 2
예제 출력 5
복사
13
힌트
-
소용돌이 예쁘게 출력하기
출처 : 소용돌이 예쁘게 출력하기
Solution
Python
import sys
input = sys.stdin.readline
# 1022번 문제를 풀기 위한 핵심 함수 (r=y(열), c=x(행))
def cal_vortex(x, y):
# x, y 둘 다 0일 때
if x == 0 and y == 0: return 1
# 다른 경우 계산 시작
n = max(abs(x), abs(y))
m = min(abs(x), abs(y))
grad = -y/x if x != 0 else 5000
# 1사분면에서 기울기가 1보다 작을 때(x축에 가까울 때), 1보다 클 때(y축에 가까울 때)
if (x >= 0 and y <= 0) and grad <= 1: var = 1+m/n
elif (x >= 0 and y <= 0) and grad >= 1: var = 3-m/n
# 2사분면에서 기울기가 -1보다 작을 때(y축에 가까울 때), -1보다 클 때(x축에 가까울 때)
elif (x <= 0 and y <= 0) and grad <= -1: var = 3+m/n
elif (x <= 0 and y <= 0) and grad >= -1: var = 5-m/n
# 3사분면에서 기울기가 1보다 작을 때(x축에 가까울 때), 1보다 클 때(y축에 가까울 때)
elif (x <= 0 and y >= 0) and grad <= 1: var = 5+m/n
elif (x <= 0 and y >= 0) and grad >= 1: var = 7-m/n
# 4사분면에서 기울기가 -1보다 작을 때(y축에 가까울 때), -1보다 클 때(x축에 가까울 때)
elif (x >= 0 and y >= 0) and grad <= -1: var = 7+m/n
elif (x >= 0 and y >= 0) and grad >= -1: var = 1-m/n
return int(1+var*n+4*n*(n-1))
r1, c1, r2, c2 = map(int, input().split())
num_r, num_c = r2-r1+1, c2-c1+1
answer = [[0] * num_c for _ in range(num_r)]
high_num = 0
for ay, ry in enumerate(range(r1, r2+1)):
for ax, cx in enumerate(range(c1, c2+1)):
answer[ay][ax] = cal_vortex(cx, ry)
if high_num < answer[ay][ax]: high_num = answer[ay][ax]
for y in range(num_r):
for x in range(num_c):
print(f'{answer[y][x]:>{len(str(high_num))}d}', end=' ')
print()
문제
크기가 무한인 정사각형 모눈종이가 있다. 모눈종이의 각 정사각형은 행과 열의 쌍으로 표현할 수 있다.
이 모눈종이 전체를 양의 정수의 소용돌이 모양으로 채울 것이다. 일단 숫자 1을 0행 0열에 쓴다. 그리고 나서 0행 1열에 숫자 2를 쓴다. 거기서 부터 소용돌이는 반시계 방향으로 시작된다. 다음 숫자는 다음과 같이 채우면 된다.
-3 -2 -1 0 1 2 3
--------------------
-3 |37 36 35 34 33 32 31
-2 |38 17 16 15 14 13 30
-1 |39 18 5 4 3 12 29
0 |40 19 6 1 2 11 28
1 |41 20 7 8 9 10 27
2 |42 21 22 23 24 25 26
3 |43 44 45 46 47 48 49
이 문제는 위와 같이 채운 것을 예쁘게 출력하면 된다. r1, c1, r2, c2가 입력으로 주어진다. r1, c1은 가장 왼쪽 위 칸이고, r2, c2는 가장 오른쪽 아래 칸이다.
예쁘게 출력한다는 것은 다음과 같이 출력하는 것이다.
출력은 r1행부터 r2행까지 차례대로 출력한다.
각 원소는 공백으로 구분한다.
모든 행은 같은 길이를 가져야 한다.
공백의 길이는 최소로 해야 한다.
모든 숫자의 길이(앞에 붙는 공백을 포함)는 같아야 한다.
만약 수의 길이가 가장 길이가 긴 수보다 작다면, 왼쪽에서부터 공백을 삽입해 길이를 맞춘다.
입력
첫째 줄에 네 정수 r1, c1, r2, c2가 주어진다.
출력
r2 - r1 + 1개의 줄에 소용돌이를 예쁘게 출력한다.
제한
-5 000 ≤ r1, c1, r2, c2 ≤ 5,000
0 ≤ r2 - r1 ≤ 49
0 ≤ c2 - c1 ≤ 4
예제 입력 1
복사
-3 -3 2 0
예제 출력 1
복사
37 36 35 34
38 17 16 15
39 18 5 4
40 19 6 1
41 20 7 8
42 21 22 23
예제 입력 2
복사
-2 2 0 3
예제 출력 2
복사
13 30
12 29
11 28
예제 입력 3
복사
-1 -2 -1 1
예제 출력 3
복사
18 5 4 3
예제 입력 4
복사
0 0 0 0
예제 출력 4
복사
1
힌트
-
수열 정렬
출처 : 수열 정렬
Solution
Python
import sys
input = sys.stdin.readline
N = int(input())
A = list(map(int, input().split()))
B = sorted(list(enumerate(A)), key = lambda x: x[1])
B = sorted(list(enumerate(B)), key = lambda x: x[1][0])
for i in B:
print(i[0], end = ' ')
문제
P[0], P[1], ...., P[N-1]은 0부터 N-1까지(포함)의 수를 한 번씩 포함하고 있는 수열이다. 수열 P를 길이가 N인 배열 A에 적용하면 길이가 N인 배열 B가 된다. 적용하는 방법은 B[P[i]] = A[i]이다.
배열 A가 주어졌을 때, 수열 P를 적용한 결과가 비내림차순이 되는 수열을 찾는 프로그램을 작성하시오. 비내림차순이란, 각각의 원소가 바로 앞에 있는 원소보다 크거나 같을 경우를 말한다. 만약 그러한 수열이 여러개라면 사전순으로 앞서는 것을 출력한다.
입력
첫째 줄에 배열 A의 크기 N이 주어진다. 둘째 줄에는 배열 A의 원소가 0번부터 차례대로 주어진다. N은 50보다 작거나 같은 자연수이고, 배열의 원소는 1,000보다 작거나 같은 자연수이다.
출력
첫째 줄에 비내림차순으로 만드는 수열 P를 출력한다.
제한
예제 입력 1
복사
3
2 3 1
예제 출력 1
복사
1 2 0
예제 입력 2
복사
4
2 1 3 1
예제 출력 2
복사
2 0 3 1
예제 입력 3
복사
8
4 1 6 1 3 6 1 4
예제 출력 3
복사
4 0 6 1 3 7 2 5
힌트
-
ACM Craft
출처 : ACM Craft
Solution
Python
import sys
sys.setrecursionlimit(10**6) # 재귀함수 최대 깊이
input = sys.stdin.readline
import time
def sum_up_D(BD, tmp):
global result
tmp += BD.D
if len(BD.X) == 0:
result = tmp if tmp > result else result
else:
for i in BD.X:
sum_up_D(H[i], tmp)
def get_cost(n):
rD = 0
for i in H[n].X:
if H[i].rD == -1:
H[i].rD = get_cost(i)
rD = rD if rD > H[i].rD else H[i].rD
return rD + H[n].D
'''
# 챗GPT의 알고리즘 분석 결과
sum_up_D 알고리즘:
재귀 호출을 통해 건물을 건설하는데 필요한 총 시간을 계산합니다.
이미 방문한 건물에 대해 결과를 기억하지 않고, 항상 전체 계산을 수행합니다.
결과를 전역 변수인 result에 저장하고 갱신합니다.
get_cost 알고리즘:
동적 계획법(Dynamic Programming)의 원리를 활용하여 중복 계산을 피하려고 노력합니다.
각 건물에 대한 최소 시간을 메모이제이션(기억)하여 중복 계산을 방지합니다.
이미 계산된 값을 활용하여 더 효율적으로 결과를 도출합니다.
'''
class building():
def __init__(self):
self.D = -1 # 걸리는 시간
self.X = [] # 이전에 지어야할 건물
self.rD = -1 # 해당 건물 완공에 요구되는 최소 시간
T = int(input()) # T : 테스트케이스 수
sum_time = 0
for t in range(T):
N, K = map(int, input().split()) # N : 건물 개수 / K : 건설순서 규칙의 수
H = [] # H : 각 건물의 갯수
D_list = list(map(int, input().split())) # 각 건물 당 건설에 걸리는 시간 입력
for D in D_list:
tmp = building()
tmp.D = D
H.append(tmp)
for i in range(K):
X, Y = map(int, input().split()) # X : 선순위 건물 / Y : 후순위 건물
# X, Y 를 계산하기 편하게 index 값으로 변경
X -= 1
Y -= 1
# 각 건물에 우선에 지어야할 건물과 이후에 지을 건물 집어넣기
H[Y].X.append(X)
W = int(input()) # 승리 조건 건물 번호
W -= 1 # 마찬가지로 index로 변경
# All_time : 0.001670361 sec
start = time.time()
sum = 0
result = 0
sum_up_D(H[W], sum)
print(result)
end = time.time()
print(f"spend_time : {end - start:.5f} sec")
sum_time += end-start
# All_time : 0.000703335 sec
start = time.time()
H[W].rD = get_cost(W)
print(H[W].rD)
end = time.time()
print(f"spend_time : {end - start:.5f} sec")
sum_time += end-start
print(f"All_time : {sum_time:.9f} sec")
문제
서기 2012년! 드디어 2년간 수많은 국민들을 기다리게 한 게임 ACM Craft (Association of Construction Manager Craft)가 발매되었다.
이 게임은 지금까지 나온 게임들과는 다르게 ACM크래프트는 다이나믹한 게임 진행을 위해 건물을 짓는 순서가 정해져 있지 않다. 즉, 첫 번째 게임과 두 번째 게임이 건물을 짓는 순서가 다를 수도 있다. 매 게임시작 시 건물을 짓는 순서가 주어진다. 또한 모든 건물은 각각 건설을 시작하여 완성이 될 때까지 Delay가 존재한다.
위의 예시를 보자.
이번 게임에서는 다음과 같이 건설 순서 규칙이 주어졌다. 1번 건물의 건설이 완료된다면 2번과 3번의 건설을 시작할수 있다. (동시에 진행이 가능하다) 그리고 4번 건물을 짓기 위해서는 2번과 3번 건물이 모두 건설 완료되어야지만 4번건물의 건설을 시작할수 있다.
따라서 4번건물의 건설을 완료하기 위해서는 우선 처음 1번 건물을 건설하는데 10초가 소요된다. 그리고 2번 건물과 3번 건물을 동시에 건설하기 시작하면 2번은 1초뒤에 건설이 완료되지만 아직 3번 건물이 완료되지 않았으므로 4번 건물을 건설할 수 없다. 3번 건물이 완성되고 나면 그때 4번 건물을 지을수 있으므로 4번 건물이 완성되기까지는 총 120초가 소요된다.
프로게이머 최백준은 애인과의 데이트 비용을 마련하기 위해 서강대학교배 ACM크래프트 대회에 참가했다! 최백준은 화려한 컨트롤 실력을 가지고 있기 때문에 모든 경기에서 특정 건물만 짓는다면 무조건 게임에서 이길 수 있다. 그러나 매 게임마다 특정건물을 짓기 위한 순서가 달라지므로 최백준은 좌절하고 있었다. 백준이를 위해 특정건물을 가장 빨리 지을 때까지 걸리는 최소시간을 알아내는 프로그램을 작성해주자.
입력
첫째 줄에는 테스트케이스의 개수 T가 주어진다. 각 테스트 케이스는 다음과 같이 주어진다. 첫째 줄에 건물의 개수 N과 건물간의 건설순서 규칙의 총 개수 K이 주어진다. (건물의 번호는 1번부터 N번까지 존재한다)
둘째 줄에는 각 건물당 건설에 걸리는 시간 D1, D2, ..., DN이 공백을 사이로 주어진다. 셋째 줄부터 K+2줄까지 건설순서 X Y가 주어진다. (이는 건물 X를 지은 다음에 건물 Y를 짓는 것이 가능하다는 의미이다)
마지막 줄에는 백준이가 승리하기 위해 건설해야 할 건물의 번호 W가 주어진다.
출력
건물 W를 건설완료 하는데 드는 최소 시간을 출력한다. 편의상 건물을 짓는 명령을 내리는 데는 시간이 소요되지 않는다고 가정한다.
건설순서는 모든 건물이 건설 가능하도록 주어진다.
제한
2 ≤ N ≤ 1000
1 ≤ K ≤ 100,000
1 ≤ X, Y, W ≤ N
0 ≤ Di ≤ 100,000, Di는 정수
예제 입력 1
복사
2
4 4
10 1 100 10
1 2
1 3
2 4
3 4
4
8 8
10 20 1 5 8 7 1 43
1 2
1 3
2 4
2 5
3 6
5 7
6 7
7 8
7
예제 출력 1
복사
120
39
예제 입력 2
복사
5
3 2
1 2 3
3 2
2 1
1
4 3
5 5 5 5
1 2
1 3
2 3
4
5 10
100000 99999 99997 99994 99990
4 5
3 5
3 4
2 5
2 4
2 3
1 5
1 4
1 3
1 2
4
4 3
1 1 1 1
1 2
3 2
1 4
4
7 8
0 0 0 0 0 0 0
1 2
1 3
2 4
3 4
4 5
4 6
5 7
6 7
7
예제 출력 2
복사
6
5
399990
2
0
힌트
-
피보나치 함수
출처 : 피보나치 함수
Solution
Python
import sys
input = sys.stdin.readline
def fibonacci(n):
result = [0] * (n+1)
result[1] = 1
for i in range(2, n+1):
result[i] = result[i-2] + result[i-1]
return result
T = int(input())
for i in range(T):
N = int(input())
if N == 0:
print('1 0')
else:
answer = fibonacci(N)
print(answer[N-1], answer[N])
문제
다음 소스는 N번째 피보나치 수를 구하는 C++ 함수이다.
int fibonacci(int n) {
if (n == 0) {
printf("0");
return 0;
} else if (n == 1) {
printf("1");
return 1;
} else {
return fibonacci(n‐1) + fibonacci(n‐2);
}
}
fibonacci(3)을 호출하면 다음과 같은 일이 일어난다.
fibonacci(3)은 fibonacci(2)와 fibonacci(1) (첫 번째 호출)을 호출한다.
fibonacci(2)는 fibonacci(1) (두 번째 호출)과 fibonacci(0)을 호출한다.
두 번째 호출한 fibonacci(1)은 1을 출력하고 1을 리턴한다.
fibonacci(0)은 0을 출력하고, 0을 리턴한다.
fibonacci(2)는 fibonacci(1)과 fibonacci(0)의 결과를 얻고, 1을 리턴한다.
첫 번째 호출한 fibonacci(1)은 1을 출력하고, 1을 리턴한다.
fibonacci(3)은 fibonacci(2)와 fibonacci(1)의 결과를 얻고, 2를 리턴한다.
1은 2번 출력되고, 0은 1번 출력된다. N이 주어졌을 때, fibonacci(N)을 호출했을 때, 0과 1이 각각 몇 번 출력되는지 구하는 프로그램을 작성하시오.
입력
첫째 줄에 테스트 케이스의 개수 T가 주어진다.
각 테스트 케이스는 한 줄로 이루어져 있고, N이 주어진다. N은 40보다 작거나 같은 자연수 또는 0이다.
출력
각 테스트 케이스마다 0이 출력되는 횟수와 1이 출력되는 횟수를 공백으로 구분해서 출력한다.
제한
예제 입력 1
복사
3
0
1
3
예제 출력 1
복사
1 0
0 1
1 2
예제 입력 2
복사
2
6
22
예제 출력 2
복사
5 8
10946 17711
힌트
-
N-Queen
출처 : N-Queen
Solution
Python
import sys
input = sys.stdin.readline
# 백트래킹 코드
def back(N, y, answer):
# 이번에 확인하는 퀸이 마지막 퀸이라면, +1
if y==N:
return answer+1
for x in range(N):
se, sw = y-x, y+x
# 중복된 x거나, 대각선 위치로 영향 미치는게 있으면 넘김
if q[x] or seL[se] or swL[sw]: continue
# 안전위치라면 해당 위치는 방문 체크
q[x] = seL[se] = swL[sw] = True
# 다음으로 퀸 놓을 수 있는 위치 확인
answer = back(N, y+1, answer)
# 백트래킹으로 진행하니 돌아오면 False로 변경
q[x] = seL[se] = swL[sw] = False
return answer
# 퀸은 가로,세로 같은 줄에 한 개씩만 위치할 수 있다.
# → 세로(y) 에 대해서 for 탐색, 가로(x)에 대해서는 겹치지만 않으면 된다.
if __name__ == '__main__':
N = int(input())
# 퀸 위치, 남동 대각선(y-x) 유효, 남서(y+x) 대각선 유효 여부 저장
q, seL, swL = [False]*N, [False]*(N*2-1), [False]*(N*2-1)
# 백트래킹 돌리고, 결과 출력
answer = back(N, 0, 0)
print(answer)
문제
N-Queen 문제는 크기가 N × N인 체스판 위에 퀸 N개를 서로 공격할 수 없게 놓는 문제이다.
N이 주어졌을 때, 퀸을 놓는 방법의 수를 구하는 프로그램을 작성하시오.
입력
첫째 줄에 N이 주어진다. (1 ≤ N < 15)
출력
첫째 줄에 퀸 N개를 서로 공격할 수 없게 놓는 경우의 수를 출력한다.
제한
예제 입력 1
복사
8
예제 출력 1
복사
92
힌트
-
-
카잉 달력
출처 : 카잉 달력
Solution
Python
import sys
input = sys.stdin.readline
import math
def solution(M, N, x, y):
# 종말의 년도 k, 현재 년도 h(x년도부터 체크)
k, h = math.lcm(M, N), x
# 종말의 날이 될 때까지 체크
while h <= k:
# h에서 y를 빼고 N의 배수인지 체크한다(x부터 시작해서 이미 h는 M의 배수임)
if (h-y)%N==0: return h
# h를 x년도부터 세니까 M을 더하면서 체크해준다.
h += M
# 끝까지 체크 못했다면 -1을 반환
return -1
if __name__ == '__main__':
T = int(input())
for _ in range(T):
M, N, x, y = map(int, input().split())
print(solution(M, N, x, y))
문제
최근에 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
힌트
W3sicHJvYmxlbV9pZCI6IjYwNjQiLCJwcm9ibGVtX2xhbmciOiIwIiwidGl0bGUiOiJcdWNlNzRcdWM3ODkgXHViMmVjXHViODI1IiwiZGVzY3JpcHRpb24iOiI8cD5cdWNkNWNcdWFkZmNcdWM1ZDAgSUNQQyBcdWQwZDBcdWMwYWNcdWIzMDBcdWIyOTQgXHViMGE4XHVjNTQ0XHViYTU0XHViOWFjXHVjZTc0XHVjNzU4IFx1Yzc4OVx1Y2U3NCBcdWM4MWNcdWFkNmRcdWM3NzQgXHViMTgwXHViNzdjXHVjNmI0IFx1YmIzOFx1YmE4NVx1Yzc0NCBcdWM5YzBcdWIyY2MgXHVjZTc0XHVjNzg5IFx1YzgxY1x1YWQ2ZFx1Yzc0NCBcdWQxYTBcdWIzMDBcdWI4NWMgXHVkNTU4XHVjNWVjIFx1YzEzOFx1YzZjY1x1Yzg0Y1x1YjJlNFx1YjI5NCBcdWMwYWNcdWMyZTRcdWM3NDQgXHViYzFjXHVhY2FjXHVkNTg4XHViMmU0LiBcdWNlNzRcdWM3ODkgXHVjODFjXHVhZDZkXHVjNzU4IFx1YmMzMVx1YzEzMVx1YjRlNFx1Yzc0MCBcdWQyYjlcdWM3NzRcdWQ1NWMgXHViMmVjXHViODI1XHVjNzQ0IFx1YzBhY1x1YzZhOVx1ZDU1YyBcdWFjODNcdWM3M2NcdWI4NWMgXHVjNTRjXHViODI0XHVjODM4IFx1Yzc4OFx1YjJlNC4gXHVhZGY4XHViNGU0XHVjNzQwIE1cdWFjZmMgTlx1YmNmNFx1YjJlNCBcdWM3OTFcdWFjNzBcdWIwOTggXHVhYzE5XHVjNzQwIFx1YjQ1MCBcdWFjMWNcdWM3NTggXHVjNzkwXHVjNWYwXHVjMjE4IHgsIHlcdWI5N2MgXHVhYzAwXHVjOWMwXHVhY2UwIFx1YWMwMSBcdWIxNDRcdWIzYzRcdWI5N2MgJmx0O3g6eSZndDtcdWM2NDAgXHVhYzE5XHVjNzQwIFx1ZDYxNVx1YzJkZFx1YzczY1x1Yjg1YyBcdWQ0NWNcdWQ2MDRcdWQ1NThcdWM2MDBcdWIyZTQuIFx1YWRmOFx1YjRlNFx1Yzc0MCBcdWM3NzQgXHVjMTM4XHVjMGMxXHVjNzU4IFx1YzJkY1x1Y2QwOFx1YzVkMCBcdWQ1NzRcdWIyZjlcdWQ1NThcdWIyOTQgXHVjY2FiIFx1YmM4OFx1YzlmOCBcdWQ1NzRcdWI5N2MgJmx0OzE6MSZndDtcdWI4NWMgXHVkNDVjXHVkNjA0XHVkNTU4XHVhY2UwLCBcdWI0NTAgXHViYzg4XHVjOWY4IFx1ZDU3NFx1Yjk3YyAmbHQ7MjoyJmd0O1x1Yjg1YyBcdWQ0NWNcdWQ2MDRcdWQ1NThcdWM2MDBcdWIyZTQuICZsdDt4OnkmZ3Q7XHVjNzU4IFx1YjJlNFx1Yzc0YyBcdWQ1NzRcdWI5N2MgXHVkNDVjXHVkNjA0XHVkNTVjIFx1YWM4M1x1Yzc0NCAmbHQ7eCYjMzk7OnkmIzM5OyZndDtcdWM3NzRcdWI3N2NcdWFjZTAgXHVkNTU4XHVjNzkwLiBcdWI5Y2NcdWM3N2MgeCAmbHQ7IE0gXHVjNzc0XHViYTc0IHgmIzM5OyA9IHggKyAxXHVjNzc0XHVhY2UwLCBcdWFkZjhcdWI4MDdcdWM5YzAgXHVjNTRhXHVjNzNjXHViYTc0IHgmIzM5OyA9IDFcdWM3NzRcdWIyZTQuIFx1YWMxOVx1Yzc0MCBcdWJjMjlcdWMyZGRcdWM3M2NcdWI4NWMgXHViOWNjXHVjNzdjIHkgJmx0OyBOXHVjNzc0XHViYTc0IHkmIzM5OyA9IHkgKyAxXHVjNzc0XHVhY2UwLCBcdWFkZjhcdWI4MDdcdWM5YzAgXHVjNTRhXHVjNzNjXHViYTc0IHkmIzM5OyA9IDFcdWM3NzRcdWIyZTQuICZsdDtNOk4mZ3Q7XHVjNzQwIFx1YWRmOFx1YjRlNCBcdWIyZWNcdWI4MjVcdWM3NTggXHViOWM4XHVjOWMwXHViOWM5IFx1ZDU3NFx1Yjg1Y1x1YzExYywgXHVjNzc0IFx1ZDU3NFx1YzVkMCBcdWMxMzhcdWMwYzFcdWM3NTggXHVjODg1XHViOWQwXHVjNzc0IFx1YjNjNFx1Yjc5OFx1ZDU1Y1x1YjJlNFx1YjI5NCBcdWM2MDhcdWM1YjhcdWM3NzQgXHVjODA0XHVkNTc0IFx1YzYyOFx1YjJlNC48XC9wPlxyXG5cclxuPHA+XHVjNjA4XHViOTdjIFx1YjRlNFx1YzViNCwgTSA9IDEwIFx1Yzc3NFx1YWNlMCBOID0gMTJcdWI3N2NcdWFjZTAgXHVkNTU4XHVjNzkwLiBcdWNjYWIgXHViYzg4XHVjOWY4IFx1ZDU3NFx1YjI5NCAmbHQ7MToxJmd0O1x1Yjg1YyBcdWQ0NWNcdWQ2MDRcdWI0MThcdWFjZTAsIDExXHViYzg4XHVjOWY4IFx1ZDU3NFx1YjI5NCAmbHQ7MToxMSZndDtcdWI4NWMgXHVkNDVjXHVkNjA0XHViNDFjXHViMmU0LiAmbHQ7MzoxJmd0O1x1Yzc0MCAxM1x1YmM4OFx1YzlmOCBcdWQ1NzRcdWI5N2MgXHViMDk4XHVkMGMwXHViMGI0XHVhY2UwLCAmbHQ7MTA6MTImZ3Q7XHViMjk0IFx1YjljOFx1YzljMFx1YjljOVx1Yzc3OCA2MFx1YmM4OFx1YzlmOCBcdWQ1NzRcdWI5N2MgXHViMDk4XHVkMGMwXHViMGI4XHViMmU0LjxcL3A+XHJcblxyXG48cD5cdWIxMjQgXHVhYzFjXHVjNzU4IFx1YzgxNVx1YzIxOCBNLCBOLCB4XHVjNjQwIHlcdWFjMDAgXHVjOGZjXHVjNWI0XHVjOWM4IFx1YjU0YywgJmx0O006TiZndDtcdWM3NzQgXHVjZTc0XHVjNzg5IFx1YjJlY1x1YjgyNVx1Yzc1OCBcdWI5YzhcdWM5YzBcdWI5YzkgXHVkNTc0XHViNzdjXHVhY2UwIFx1ZDU1OFx1YmE3NCAmbHQ7eDp5Jmd0O1x1YjI5NCBcdWJhODcgXHViYzg4XHVjOWY4IFx1ZDU3NFx1Yjk3YyBcdWIwOThcdWQwYzBcdWIwYjRcdWIyOTRcdWM5YzAgXHVhZDZjXHVkNTU4XHViMjk0IFx1ZDUwNFx1Yjg1Y1x1YWRmOFx1YjdhOFx1Yzc0NCBcdWM3OTFcdWMxMzFcdWQ1NThcdWI3N2MuPFwvcD5cclxuIiwiaW5wdXQiOiI8cD5cdWM3ODVcdWI4MjUgXHViMzcwXHVjNzc0XHVkMTMwXHViMjk0IFx1ZDQ1Y1x1YzkwMCBcdWM3ODVcdWI4MjVcdWM3NDQgXHVjMGFjXHVjNmE5XHVkNTVjXHViMmU0LiBcdWM3ODVcdWI4MjVcdWM3NDAgVFx1YWMxY1x1Yzc1OCBcdWQxNGNcdWMyYTRcdWQyYjggXHViMzcwXHVjNzc0XHVkMTMwXHViODVjIFx1YWQ2Y1x1YzEzMVx1YjQxY1x1YjJlNC4gXHVjNzg1XHViODI1XHVjNzU4IFx1Y2NhYiBcdWJjODhcdWM5ZjggXHVjOTA0XHVjNWQwXHViMjk0IFx1Yzc4NVx1YjgyNSBcdWIzNzBcdWM3NzRcdWQxMzBcdWM3NTggXHVjMjE4XHViOTdjIFx1YjA5OFx1ZDBjMFx1YjBiNFx1YjI5NCBcdWM4MTVcdWMyMTggVFx1YWMwMCBcdWM4ZmNcdWM1YjRcdWM5YzRcdWIyZTQuIFx1YWMwMSBcdWQxNGNcdWMyYTRcdWQyYjggXHViMzcwXHVjNzc0XHVkMTMwXHViMjk0IFx1ZDU1YyBcdWM5MDRcdWI4NWMgXHVhZDZjXHVjMTMxXHViNDFjXHViMmU0LiBcdWFjMDEgXHVjOTA0XHVjNWQwXHViMjk0IFx1YjEyNCBcdWFjMWNcdWM3NTggXHVjODE1XHVjMjE4IE0sIE4sIHhcdWM2NDAgeVx1YWMwMCBcdWM4ZmNcdWM1YjRcdWM5YzRcdWIyZTQuICgxICZsZTsgTSwgTiAmbGU7IDQwLDAwMCwgMSAmbGU7IHggJmxlOyBNLCAxICZsZTsgeSAmbGU7IE4pIFx1YzVlY1x1YWUzMFx1YzExYyAmbHQ7TTpOJmd0O1x1Yzc0MCBcdWNlNzRcdWM3ODkgXHViMmVjXHViODI1XHVjNzU4IFx1YjljOFx1YzljMFx1YjljOSBcdWQ1NzRcdWI5N2MgXHViMDk4XHVkMGMwXHViMGI4XHViMmU0LjxcL3A+XHJcbiIsIm91dHB1dCI6IjxwPlx1Y2Q5Y1x1YjgyNVx1Yzc0MCBcdWQ0NWNcdWM5MDAgXHVjZDljXHViODI1XHVjNzQ0IFx1YzBhY1x1YzZhOVx1ZDU1Y1x1YjJlNC4gXHVhYzAxIFx1ZDE0Y1x1YzJhNFx1ZDJiOCBcdWIzNzBcdWM3NzRcdWQxMzBcdWM1ZDAgXHViMzAwXHVkNTc0LCBcdWM4MTVcdWMyMTgga1x1Yjk3YyBcdWQ1NWMgXHVjOTA0XHVjNWQwIFx1Y2Q5Y1x1YjgyNVx1ZDU1Y1x1YjJlNC4gXHVjNWVjXHVhZTMwXHVjMTFjIGtcdWIyOTQgJmx0O3g6eSZndDtcdWFjMDAga1x1YmM4OFx1YzlmOCBcdWQ1NzRcdWI5N2MgXHViMDk4XHVkMGMwXHViMGI0XHViMjk0IFx1YWM4M1x1Yzc0NCBcdWM3NThcdWJiZjhcdWQ1NWNcdWIyZTQuIFx1YjljY1x1Yzc3YyAmbHQ7eDp5Jmd0O1x1YzVkMCBcdWM3NThcdWQ1NzQgXHVkNDVjXHVkNjA0XHViNDE4XHViMjk0IFx1ZDU3NFx1YWMwMCBcdWM1YzZcdWIyZTRcdWJhNzQsIFx1Yzk4OSwgJmx0O3g6eSZndDtcdWFjMDAgXHVjNzIwXHVkNmE4XHVkNTU4XHVjOWMwIFx1YzU0YVx1Yzc0MCBcdWQ0NWNcdWQ2MDRcdWM3NzRcdWJhNzQsIC0xXHVjNzQ0IFx1Y2Q5Y1x1YjgyNVx1ZDU1Y1x1YjJlNC48XC9wPlxyXG4iLCJoaW50IjoiIiwib3JpZ2luYWwiOiIwIiwiaHRtbF90aXRsZSI6IjAiLCJwcm9ibGVtX2xhbmdfdGNvZGUiOiJLb3JlYW4ifSx7InByb2JsZW1faWQiOiI2MDY0IiwicHJvYmxlbV9sYW5nIjoiMSIsInRpdGxlIjoiQ2FpbiBDYWxlbmRhciIsImRlc2NyaXB0aW9uIjoiPHA+SXQgd2FzIHJlY2VudGx5IHJldmVhbGVkIGJ5IHRoZSBJQ1BDIGV4Y2F2YXRpb24gdGVhbSB0aGF0IHRoZSBJbmNhIEVtcGlyZSB3YXMgZXN0YWJsaXNoZWQganVzdCBhZnRlciB0aGUgQ2FpbiBFbXBpcmUgd2hpY2ggd2FzIGEgc3BsZW5kaWQgY2l2aWxpemF0aW9uIHRoYXQgZmxvdXJpc2hlZCBpbiBTb3V0aCBBbWVyaWNhLiBJdCBpcyBiZWxpZXZlZCB0aGF0IHRoZSBwZW9wbGUgaW4gdGhlIENhaW4gRW1waXJlIHVzZWQgYW4gaW50ZXJlc3Rpbmcgb2RkIGNhbGVuZGFyLiBJbiB0aGVpciBjYWxlbmRhciwgYSB5ZWFyIHdhcyByZXByZXNlbnRlZCBieSAmbHQ7eDp5Jmd0Oywgd2hlcmUgeCBhbmQgeSBhcmUgbmF0dXJhbCBudW1iZXJzIHdoaWNoIGFyZSBsZXNzIHRoYW4gb3IgZXF1YWwgdG8gTSBhbmQgTiwgcmVzcGVjdGl2ZWx5LiBUaGUgZmlyc3QgeWVhciwgdGhhdCBpcywgdGhlIGJlZ2lubmluZyBvZiB0aGUgd29ybGQgaXMgcmVwcmVzZW50ZWQgYnkgJmx0OzE6MSZndDsuIFRoZSBzZWNvbmQgeWVhciBpcyByZXByZXNlbnRlZCBieSAmbHQ7MjoyJmd0Oy4gTGV0ICZsdDt4JiMzOTs6eSYjMzk7Jmd0O2JlIHRoZSBmb2xsb3dpbmcgeWVhciBvZiAmbHQ7eDp5Jmd0Oy4gSWYgeCAmbHQ7IE0sIHgmIzM5OyA9IHggKyAxLCBvdGhlcndpc2UgeCYjMzk7ID0gMS4gU2ltaWxhcmx5LCBpZiB5ICZsdDsgTiwgeSYjMzk7ID0geSArIDEsIG90aGVyd2lzZSB5JiMzOTsgPSAxLiBUaGUgbGFzdCB5ZWFyIG9mIHRoZWlyIGNhbGVuZGFyIGlzICZsdDtNOk4mZ3Q7LiBJdCBpcyBzYWlkIHRoYXQgdGhlcmUgd2FzIGEgcHJvcGhlY3kgd2hpY2ggc3RhdGVzIHRoZSB3b3JsZCBlbmRzIGluIHRoZSB5ZWFyICZsdDtNOk4mZ3Q7LiZuYnNwOzxcL3A+XHJcblxyXG48cD5Gb3IgZXhhbXBsZSwgYXNzdW1lIHRoYXQgTSA9IDEwIGFuZCBOID0gMTIuIFRoZSBmaXJzdCB5ZWFyIGlzIHJlcHJlc2VudGVkIGJ5ICZsdDsxOjEmZ3Q7LiBUaGUgeWVhciAmbHQ7MToxMSZndDsgcmVwcmVzZW50cyB0aGUgMTE8c3VwPnRoPFwvc3VwPiB5ZWFyLCAmbHQ7MzoxJmd0OyByZXByZXNlbnRzIHRoZSAxMzxzdXA+dGg8XC9zdXA+IHllYXIsIGFuZCAmbHQ7MTA6MTImZ3Q7IHJlcHJlc2VudHMgdGhlIDYwPHN1cD50aDxcL3N1cD4geWVhciB3aGljaCBpcyB0aGUgbGFzdCB5ZWFyLiZuYnNwOzxcL3A+XHJcblxyXG48cD5HaXZlbiBmb3VyIGludGVnZXJzIE0sIE4sIHgsIGFuZCB5LCB3cml0ZSBhIHByb2dyYW0gdGhhdCBjb21wdXRlcyB0aGUgbnVtYmVyIGsgc3VjaCB0aGF0ICZsdDt4OnkmZ3Q7IHJlcHJlc2VudHMgdGhlIGs8c3VwPnRoPFwvc3VwPiB5ZWFyLCB3aGVyZSAmbHQ7eDp5Jmd0OyBpcyB0aGUgbGFzdCB5ZWFyIG9mIHRoZSB3b3JsZCBpbiB0aGUgQ2FpbiBDYWxlbmRhci48XC9wPlxyXG4iLCJpbnB1dCI6IjxwPllvdXIgcHJvZ3JhbSBpcyB0byByZWFkIGZyb20gc3RhbmRhcmQgaW5wdXQuIFRoZSBpbnB1dCBjb25zaXN0cyBvZiBUIHRlc3QgY2FzZXMuIFRoZSBudW1iZXIgb2YgdGVzdCBjYXNlcyBUIGlzIGdpdmVuIGluIHRoZSBmaXJzdCBsaW5lIG9mIHRoZSBpbnB1dC4gRWFjaCB0ZXN0IGNhc2UgY29uc2lzdHMgb2YgYSBzaW5nbGUgbGluZSBjb250YWluaW5nIGZvdXIgaW50ZWdlcnMgTSwgTiwgeCwgYW5kIHkgKDEgJmxlOyBNLE4gJmxlOyA0MCAwMDAsIDEgJmxlOyB4ICZsZTsgTSwgMSAmbGU7IHkgJmxlOyBOKSwgd2hlcmUgJmx0O006TiZndDsgaXMgdGhlIGxhc3QgeWVhciBvZiB0aGUgd29ybGQgaW4gdGhlIENhaW4gQ2FsZW5kYXIuPFwvcD5cclxuIiwib3V0cHV0IjoiPHA+WW91ciBwcm9ncmFtIGlzIHRvIHdyaXRlIHRvIHN0YW5kYXJkIG91dHB1dC4gUHJpbnQgZXhhY3RseSBvbmUgbGluZSBmb3IgZWFjaCB0ZXN0IGNhc2UuIFRoZSBsaW5lIHNob3VsZCBjb250YWluIGFuIGludGVnZXIgaywgd2hlcmUgdGhlIGs8c3VwPnRoPFwvc3VwPiB5ZWFyIGlzIHJlcHJlc2VudGVkIGJ5ICZsdDt4OnkmZ3Q7IGZvciB4IGFuZCB5IGdpdmVuIGluIHRoZSBpbnB1dC4gSWYgdGhlcmUgZG9lc24mcnNxdW87dCBleGlzdCBhIHllYXIgcmVwcmVzZW50ZWQgYnkgJmx0O3g6eSZndDssIHByaW50IC0xLiZuYnNwOzxcL3A+XHJcbiIsImhpbnQiOiIiLCJvcmlnaW5hbCI6IjEiLCJodG1sX3RpdGxlIjoiMCIsInByb2JsZW1fbGFuZ190Y29kZSI6IkVuZ2xpc2gifV0=
-
전화번호 목록
출처 : 전화번호 목록
Solution
Python
import sys
input = sys.stdin.readline
# 트라이 구조 활용
class Node(object):
def __init__(self, key, data=None):
self.key = key
self.data = data
self.child = {}
class Trie(object):
def __init__(self):
self.head = Node(None)
def insert(self, lst):
# 현재 노드 위치 가리키는 now
now = self.head
# 문자 하나씩 key로 잡고, 노드를 만들어서 내려감
for c in lst:
if c not in now.child:
now.child[c] = Node(c)
now = now.child[c]
# lst의 모든 문자를 key로 해서 노드가 만들어졌으면, 마지막 노드에 data 추가
now.data = lst
def search(self, lst):
# 현재 노드 위치 가리키는 now
now = self.head
# 만들어둔 트라이 구조에서 lst를 끝까지 검색
for c in lst:
now = now.child[c]
# 검색 결과 하위 노드가 있다면(접두어라면) False
if now.child: return False
# 없다면 True
else: return True
if __name__ == '__main__':
t = int(input())
for _ in range(t):
n = int(input())
# 예제 1번 보면 공백은 없애는게 맞음
phone = [input().strip().replace(' ', '') for _ in range(n)]
# 각 TC에 대해 트라이 구조 생성
trie = Trie()
# 각 번호들을 트라이 구조에 입력
for lst in phone: trie.insert(lst)
# 유효한 목록인지 체크할 변수 flag
flag = True
# 각 번호를 검색하며, 한번이라도 유효하지 않으면 False로 변환
for lst in phone:
if not trie.search(lst):
flag = False
break
# 유효하면 YES, 유효하지 않으면 NO
if flag: print('YES')
else: print('NO')
'''
# sort하면 사전순 우선 정렬 후 길이 짧은 것부터 정렬되는 특성 활용
def valid(lst):
# 이미 정렬됐으니까, 목록에서 i-1이 i의 접두어인지만 확인하면 됨.
for i in range(1, len(lst)):
# 목록에서 앞 번호 길이가 뒷 번호 길이 이상이라면, 접두어가 아니니 패스
n, m = len(lst[i-1]), len(lst[i])
if n >= m: continue
# i에서 n까지의 번호가 i-1의 접두어인지 체크
if lst[i-1]==lst[i][:n]: return False
return True
if __name__ == '__main__':
t = int(input())
for _ in range(t):
n = int(input())
# 예제 1번 보면 공백은 없애는게 맞음
phone = [input().strip().replace(' ', '') for _ in range(n)]
# 우선 정렬
phone.sort()
# 유효한 목록이면, YES / 아니면 NO
if valid(phone): print('YES')
else: print('NO')
'''
문제
전화번호 목록이 주어진다. 이때, 이 목록이 일관성이 있는지 없는지를 구하는 프로그램을 작성하시오.
전화번호 목록이 일관성을 유지하려면, 한 번호가 다른 번호의 접두어인 경우가 없어야 한다.
예를 들어, 전화번호 목록이 아래와 같은 경우를 생각해보자
긴급전화: 911
상근: 97 625 999
선영: 91 12 54 26
이 경우에 선영이에게 전화를 걸 수 있는 방법이 없다. 전화기를 들고 선영이 번호의 처음 세 자리를 누르는 순간 바로 긴급전화가 걸리기 때문이다. 따라서, 이 목록은 일관성이 없는 목록이다.
입력
첫째 줄에 테스트 케이스의 개수 t가 주어진다. (1 ≤ t ≤ 50) 각 테스트 케이스의 첫째 줄에는 전화번호의 수 n이 주어진다. (1 ≤ n ≤ 10000) 다음 n개의 줄에는 목록에 포함되어 있는 전화번호가 하나씩 주어진다. 전화번호의 길이는 길어야 10자리이며, 목록에 있는 두 전화번호가 같은 경우는 없다.
출력
각 테스트 케이스에 대해서, 일관성 있는 목록인 경우에는 YES, 아닌 경우에는 NO를 출력한다.
제한
예제 입력 1
복사
2
3
911
97625999
91125426
5
113
12340
123440
12345
98346
예제 출력 1
복사
NO
YES
힌트
W3sicHJvYmxlbV9pZCI6IjUwNTIiLCJwcm9ibGVtX2xhbmciOiIwIiwidGl0bGUiOiJcdWM4MDRcdWQ2NTRcdWJjODhcdWQ2MzggXHViYWE5XHViODVkIiwiZGVzY3JpcHRpb24iOiI8cD5cdWM4MDRcdWQ2NTRcdWJjODhcdWQ2MzggXHViYWE5XHViODVkXHVjNzc0IFx1YzhmY1x1YzViNFx1YzljNFx1YjJlNC4gXHVjNzc0XHViNTRjLCBcdWM3NzQgXHViYWE5XHViODVkXHVjNzc0IFx1Yzc3Y1x1YWQwMFx1YzEzMVx1Yzc3NCBcdWM3ODhcdWIyOTRcdWM5YzAgXHVjNWM2XHViMjk0XHVjOWMwXHViOTdjIFx1YWQ2Y1x1ZDU1OFx1YjI5NCBcdWQ1MDRcdWI4NWNcdWFkZjhcdWI3YThcdWM3NDQgXHVjNzkxXHVjMTMxXHVkNTU4XHVjMmRjXHVjNjI0LjxcL3A+XHJcblxyXG48cD5cdWM4MDRcdWQ2NTRcdWJjODhcdWQ2MzggXHViYWE5XHViODVkXHVjNzc0IFx1Yzc3Y1x1YWQwMFx1YzEzMVx1Yzc0NCBcdWM3MjBcdWM5YzBcdWQ1NThcdWI4MjRcdWJhNzQsIFx1ZDU1YyBcdWJjODhcdWQ2MzhcdWFjMDAgXHViMmU0XHViOTc4IFx1YmM4OFx1ZDYzOFx1Yzc1OCBcdWM4MTFcdWI0NTBcdWM1YjRcdWM3NzggXHVhY2JkXHVjNmIwXHVhYzAwIFx1YzVjNlx1YzViNFx1YzU3YyBcdWQ1NWNcdWIyZTQuPFwvcD5cclxuXHJcbjxwPlx1YzYwOFx1Yjk3YyBcdWI0ZTRcdWM1YjQsIFx1YzgwNFx1ZDY1NFx1YmM4OFx1ZDYzOCBcdWJhYTlcdWI4NWRcdWM3NzQgXHVjNTQ0XHViNzk4XHVjNjQwIFx1YWMxOVx1Yzc0MCBcdWFjYmRcdWM2YjBcdWI5N2MgXHVjMGRkXHVhYzAxXHVkNTc0XHViY2Y0XHVjNzkwPFwvcD5cclxuXHJcbjx1bD5cclxuXHQ8bGk+XHVhZTM0XHVhZTA5XHVjODA0XHVkNjU0OiA5MTE8XC9saT5cclxuXHQ8bGk+XHVjMGMxXHVhZGZjOiA5NyA2MjUgOTk5PFwvbGk+XHJcblx0PGxpPlx1YzEyMFx1YzYwMTogOTEgMTIgNTQgMjY8XC9saT5cclxuPFwvdWw+XHJcblxyXG48cD5cdWM3NzQgXHVhY2JkXHVjNmIwXHVjNWQwIFx1YzEyMFx1YzYwMVx1Yzc3NFx1YzVkMFx1YWM4YyBcdWM4MDRcdWQ2NTRcdWI5N2MgXHVhYzc4IFx1YzIxOCBcdWM3ODhcdWIyOTQgXHViYzI5XHViYzk1XHVjNzc0IFx1YzVjNlx1YjJlNC4gXHVjODA0XHVkNjU0XHVhZTMwXHViOTdjIFx1YjRlNFx1YWNlMCBcdWMxMjBcdWM2MDFcdWM3NzQgXHViYzg4XHVkNjM4XHVjNzU4IFx1Y2M5OFx1Yzc0YyBcdWMxMzggXHVjNzkwXHViOWFjXHViOTdjIFx1YjIwNFx1Yjk3NFx1YjI5NCBcdWMyMWNcdWFjMDQgXHViYzE0XHViODVjIFx1YWUzNFx1YWUwOVx1YzgwNFx1ZDY1NFx1YWMwMCBcdWFjNzhcdWI5YWNcdWFlMzAgXHViNTRjXHViYjM4XHVjNzc0XHViMmU0LiBcdWI1MzBcdWI3N2NcdWMxMWMsIFx1Yzc3NCBcdWJhYTlcdWI4NWRcdWM3NDAgXHVjNzdjXHVhZDAwXHVjMTMxXHVjNzc0IFx1YzVjNlx1YjI5NCBcdWJhYTlcdWI4NWRcdWM3NzRcdWIyZTQuIDxcL3A+XHJcbiIsImlucHV0IjoiPHA+XHVjY2FiXHVjOWY4IFx1YzkwNFx1YzVkMCBcdWQxNGNcdWMyYTRcdWQyYjggXHVjZjAwXHVjNzc0XHVjMmE0XHVjNzU4IFx1YWMxY1x1YzIxOCB0XHVhYzAwIFx1YzhmY1x1YzViNFx1YzljNFx1YjJlNC4gKDEgJmxlOyB0ICZsZTsgNTApIFx1YWMwMSBcdWQxNGNcdWMyYTRcdWQyYjggXHVjZjAwXHVjNzc0XHVjMmE0XHVjNzU4IFx1Y2NhYlx1YzlmOCBcdWM5MDRcdWM1ZDBcdWIyOTQgXHVjODA0XHVkNjU0XHViYzg4XHVkNjM4XHVjNzU4IFx1YzIxOCBuXHVjNzc0IFx1YzhmY1x1YzViNFx1YzljNFx1YjJlNC4gKDEgJmxlOyBuICZsZTsgMTAwMDApIFx1YjJlNFx1Yzc0YyBuXHVhYzFjXHVjNzU4IFx1YzkwNFx1YzVkMFx1YjI5NCBcdWJhYTlcdWI4NWRcdWM1ZDAgXHVkM2VjXHVkNTY4XHViNDE4XHVjNWI0IFx1Yzc4OFx1YjI5NCBcdWM4MDRcdWQ2NTRcdWJjODhcdWQ2MzhcdWFjMDAgXHVkNTU4XHViMDk4XHVjNTI5IFx1YzhmY1x1YzViNFx1YzljNFx1YjJlNC4gXHVjODA0XHVkNjU0XHViYzg4XHVkNjM4XHVjNzU4IFx1YWUzOFx1Yzc3NFx1YjI5NCBcdWFlMzhcdWM1YjRcdWM1N2MgMTBcdWM3OTBcdWI5YWNcdWM3NzRcdWJhNzAsIFx1YmFhOVx1Yjg1ZFx1YzVkMCBcdWM3ODhcdWIyOTQgXHViNDUwIFx1YzgwNFx1ZDY1NFx1YmM4OFx1ZDYzOFx1YWMwMCBcdWFjMTlcdWM3NDAgXHVhY2JkXHVjNmIwXHViMjk0IFx1YzVjNlx1YjJlNC48XC9wPlxyXG4iLCJvdXRwdXQiOiI8cD5cdWFjMDEgXHVkMTRjXHVjMmE0XHVkMmI4IFx1Y2YwMFx1Yzc3NFx1YzJhNFx1YzVkMCBcdWIzMDBcdWQ1NzRcdWMxMWMsIFx1Yzc3Y1x1YWQwMFx1YzEzMSBcdWM3ODhcdWIyOTQgXHViYWE5XHViODVkXHVjNzc4IFx1YWNiZFx1YzZiMFx1YzVkMFx1YjI5NCBZRVMsIFx1YzU0NFx1YjJjYyBcdWFjYmRcdWM2YjBcdWM1ZDBcdWIyOTQgTk9cdWI5N2MgXHVjZDljXHViODI1XHVkNTVjXHViMmU0LjxcL3A+XHJcbiIsImhpbnQiOiIiLCJvcmlnaW5hbCI6IjAiLCJodG1sX3RpdGxlIjoiMCIsInByb2JsZW1fbGFuZ190Y29kZSI6IktvcmVhbiJ9LHsicHJvYmxlbV9pZCI6IjUwNTIiLCJwcm9ibGVtX2xhbmciOiIxIiwidGl0bGUiOiJQaG9uZSBMaXN0IiwiZGVzY3JpcHRpb24iOiI8cD5HaXZlbiBhIGxpc3Qgb2YgcGhvbmUgbnVtYmVycywgZGV0ZXJtaW5lIGlmIGl0IGlzIGNvbnNpc3RlbnQgaW4gdGhlIHNlbnNlIHRoYXQgbm8gbnVtYmVyIGlzIHRoZSBwcmVcdWZiMDF4IG9mIGFub3RoZXIuIExldCZyc3F1bztzIHNheSB0aGUgcGhvbmUgY2F0YWxvZ3VlIGxpc3RlZCB0aGVzZSBudW1iZXJzOjxcL3A+XHJcblxyXG48dWw+XHJcblx0PGxpPkVtZXJnZW5jeSA5MTE8XC9saT5cclxuXHQ8bGk+QWxpY2UgOTcgNjI1IDk5OTxcL2xpPlxyXG5cdDxsaT5Cb2IgOTEgMTIgNTQgMjY8XC9saT5cclxuPFwvdWw+XHJcblxyXG48cD5JbiB0aGlzIGNhc2UsIGl0JnJzcXVvO3Mgbm90IHBvc3NpYmxlIHRvIGNhbGwgQm9iLCBiZWNhdXNlIHRoZSBjZW50cmFsIHdvdWxkIGRpcmVjdCB5b3VyIGNhbGwgdG8gdGhlIGVtZXJnZW5jeSBsaW5lIGFzIHNvb24gYXMgeW91IGhhZCBkaWFsbGVkIHRoZSBcdWZiMDFyc3QgdGhyZWUgZGlnaXRzIG9mIEJvYiZyc3F1bztzIHBob25lIG51bWJlci4gU28gdGhpcyBsaXN0IHdvdWxkIG5vdCBiZSBjb25zaXN0ZW50LjxcL3A+XHJcbiIsImlucHV0IjoiPHA+VGhlIFx1ZmIwMXJzdCBsaW5lIG9mIGlucHV0IGdpdmVzIGEgc2luZ2xlIGludGVnZXIsIDEgJmxlOyB0ICZsZTsgNDAsIHRoZSBudW1iZXIgb2YgdGVzdCBjYXNlcy4gRWFjaCB0ZXN0IGNhc2Ugc3RhcnRzIHdpdGggbiwgdGhlIG51bWJlciBvZiBwaG9uZSBudW1iZXJzLCBvbiBhIHNlcGFyYXRlIGxpbmUsIDEgJmxlOyBuICZsZTsgMTAwMDAuIFRoZW4gZm9sbG93cyBuIGxpbmVzIHdpdGggb25lIHVuaXF1ZSBwaG9uZSBudW1iZXIgb24gZWFjaCBsaW5lLiBBIHBob25lIG51bWJlciBpcyBhIHNlcXVlbmNlIG9mIGF0IG1vc3QgdGVuIGRpZ2l0cy48XC9wPlxyXG4iLCJvdXRwdXQiOiI8cD5Gb3IgZWFjaCB0ZXN0IGNhc2UsIG91dHB1dCAmbGRxdW87WUVTJnJkcXVvOyBpZiB0aGUgbGlzdCBpcyBjb25zaXN0ZW50LCBvciAmbGRxdW87Tk8mcmRxdW87IG90aGVyd2lzZS48XC9wPlxyXG4iLCJoaW50IjoiIiwib3JpZ2luYWwiOiIxIiwiaHRtbF90aXRsZSI6IjAiLCJwcm9ibGVtX2xhbmdfdGNvZGUiOiJFbmdsaXNoIn1d
-
동전 1
출처 : 동전 1
Solution
Python
import sys
input = sys.stdin.readline
if __name__ == '__main__':
n, k = map(int, input().split())
coins = [int(input()) for _ in range(n)]
# DP 배열 초기화
ans = [0]*(k+1)
# 0번째는 1로 초기화해야 누적합이 작동한다.
ans[0] = 1
# 각 코인(c)별로, 각 금액(i)을 채울 수 있는 경우의 수를 누적해나간다.
for c in coins:
# 누적합은 현재 코인으로 채울 수 있는 금액 차이일 때 이전 경우의 수를 더하는것
for i in range(c, k+1):
ans[i] += ans[i-c]
# k일 때의 금액을 출력
print(ans[-1])
문제
n가지 종류의 동전이 있다. 각각의 동전이 나타내는 가치는 다르다. 이 동전을 적당히 사용해서, 그 가치의 합이 k원이 되도록 하고 싶다. 그 경우의 수를 구하시오. 각각의 동전은 몇 개라도 사용할 수 있다.
사용한 동전의 구성이 같은데, 순서만 다른 것은 같은 경우이다.
입력
첫째 줄에 n, k가 주어진다. (1 ≤ n ≤ 100, 1 ≤ k ≤ 10,000) 다음 n개의 줄에는 각각의 동전의 가치가 주어진다. 동전의 가치는 100,000보다 작거나 같은 자연수이다.
출력
첫째 줄에 경우의 수를 출력한다. 경우의 수는 231보다 작다.
제한
예제 입력 1
복사
3 10
1
2
5
예제 출력 1
복사
10
힌트
-
카드2
출처 : 카드2
Solution
Python
import sys
input = sys.stdin.readline
from collections import deque
if __name__ == '__main__':
N = int(input())
Q = deque(range(1, N+1))
# 현재 해야하는 연산 체크용
chk = True
while True:
n = Q.popleft()
# Q가 비었으면 마지막에 뽑은 숫자 출력
if not Q:
print(n)
break
# 시작은 버리고, 다음부터 우측에 넣는다.
if chk: chk = False
else:
Q.append(n)
chk = True
문제
N장의 카드가 있다. 각각의 카드는 차례로 1부터 N까지의 번호가 붙어 있으며, 1번 카드가 제일 위에, N번 카드가 제일 아래인 상태로 순서대로 카드가 놓여 있다.
이제 다음과 같은 동작을 카드가 한 장 남을 때까지 반복하게 된다. 우선, 제일 위에 있는 카드를 바닥에 버린다. 그 다음, 제일 위에 있는 카드를 제일 아래에 있는 카드 밑으로 옮긴다.
예를 들어 N=4인 경우를 생각해 보자. 카드는 제일 위에서부터 1234 의 순서로 놓여있다. 1을 버리면 234가 남는다. 여기서 2를 제일 아래로 옮기면 342가 된다. 3을 버리면 42가 되고, 4를 밑으로 옮기면 24가 된다. 마지막으로 2를 버리고 나면, 남는 카드는 4가 된다.
N이 주어졌을 때, 제일 마지막에 남게 되는 카드를 구하는 프로그램을 작성하시오.
입력
첫째 줄에 정수 N(1 ≤ N ≤ 500,000)이 주어진다.
출력
첫째 줄에 남게 되는 카드의 번호를 출력한다.
제한
예제 입력 1
복사
6
예제 출력 1
복사
4
힌트
-
그림
출처 : 그림
Solution
Python
import sys
input = sys.stdin.readline
from collections import deque
def countArea(sy, sx, visited, paper, n, m):
# (y, x) : 상하좌우
direction = ((-1, 0), (1, 0), (0, -1), (0, 1))
Q = deque()
Q.append((sy, sx))
area = 0 # 현재 그림의 넓이
while Q:
y, x = Q.popleft()
# 체크한 위치면 넘김
if visited[y][x]: continue
# 체크 안한 칸이면 체크하고, 넓이 더해주기
visited[y][x] = True
area += 1
# 주변 칸 탐색
for dy, dx in direction:
ny, nx = y+dy, x+dx
if ((0 <= ny < n) & (0 <= nx < m)):
# 그림 그려진 칸일 경우 확인을 위해 Q에 추가
if paper[ny][nx]: Q.append((ny, nx))
# 그림 넓이 세기 끝났다면 반환
return visited, paper, area
if __name__=='__main__':
n, m = map(int, input().split())
paper = [list(map(int, input().split())) for _ in range(n)]
visited = [[False]*m for _ in range(n)]
drawNum = 0
drawArea = 0
# 1이 그려진 칸이라면, countArea로 그림의 넓이를 세준다.
for y in range(n):
for x in range(m):
if ((not visited[y][x]) & paper[y][x]):
drawNum += 1
visited, paper, area = countArea(y, x, visited, paper, n, m)
drawArea = max(drawArea, area)
print(drawNum)
print(drawArea)
문제
어떤 큰 도화지에 그림이 그려져 있을 때, 그 그림의 개수와, 그 그림 중 넓이가 가장 넓은 것의 넓이를 출력하여라. 단, 그림이라는 것은 1로 연결된 것을 한 그림이라고 정의하자. 가로나 세로로 연결된 것은 연결이 된 것이고 대각선으로 연결이 된 것은 떨어진 그림이다. 그림의 넓이란 그림에 포함된 1의 개수이다.
입력
첫째 줄에 도화지의 세로 크기 n(1 ≤ n ≤ 500)과 가로 크기 m(1 ≤ m ≤ 500)이 차례로 주어진다. 두 번째 줄부터 n+1 줄 까지 그림의 정보가 주어진다. (단 그림의 정보는 0과 1이 공백을 두고 주어지며, 0은 색칠이 안된 부분, 1은 색칠이 된 부분을 의미한다)
출력
첫째 줄에는 그림의 개수, 둘째 줄에는 그 중 가장 넓은 그림의 넓이를 출력하여라. 단, 그림이 하나도 없는 경우에는 가장 넓은 그림의 넓이는 0이다.
제한
예제 입력 1
복사
6 5
1 1 0 1 1
0 1 1 0 0
0 0 0 0 0
1 0 1 1 1
0 0 1 1 1
0 0 1 1 1
예제 출력 1
복사
4
9
힌트
-
수 찾기
출처 : 수 찾기
Solution
Python
import sys
input = sys.stdin.readline
def findInList(a, A, N):
# 가장 작은 값, 가장 큰 값
s, b = 0, N-1
# 이분 탐색 알고리즘
while s <= b:
n = (s+b)//2
# a를 찾으면 1 반환
if A[n]==a: return 1
# 현재 값이 a보다 크면, 큰 값을 현재 값의 -1
elif A[n] > a: b = n-1
# 현재 값이 a보다 작으면, 작은 값을 현재 값의 +1
elif A[n] < a: s = n+1
# 못 찾으면 0 반환
return 0
if __name__ == '__main__':
N = int(input())
A = list(map(int, input().split()))
M = int(input())
a = list(map(int, input().split()))
# 이진 탐색을 위해 A를 sort
A.sort()
# a 안의 각 값에 대해 이진 탐색 후 출력
for i in a:
print(findInList(i, A, N))
'''
if __name__ == '__main__':
N = int(input())
NA = list(map(int, input().split()))
M = int(input())
MA = list(map(int, input().split()))
# 해시를 이용하기 위해 dict 형태로 변환
A = {v:1 for v in NA}
# try except 구문을 활용해 간단히 풀이
for a in MA:
try:
if A[a]: print(1)
except: print(0)
'''
문제
N개의 정수 A[1], A[2], …, A[N]이 주어져 있을 때, 이 안에 X라는 정수가 존재하는지 알아내는 프로그램을 작성하시오.
입력
첫째 줄에 자연수 N(1 ≤ N ≤ 100,000)이 주어진다. 다음 줄에는 N개의 정수 A[1], A[2], …, A[N]이 주어진다. 다음 줄에는 M(1 ≤ M ≤ 100,000)이 주어진다. 다음 줄에는 M개의 수들이 주어지는데, 이 수들이 A안에 존재하는지 알아내면 된다. 모든 정수의 범위는 -231 보다 크거나 같고 231보다 작다.
출력
M개의 줄에 답을 출력한다. 존재하면 1을, 존재하지 않으면 0을 출력한다.
제한
예제 입력 1
복사
5
4 1 5 2 3
5
1 3 7 9 5
예제 출력 1
복사
1
1
0
0
1
힌트
-
스티커 붙이기
출처 : 스티커 붙이기
Solution
Python
import sys
input = sys.stdin.readline
# 시계 방향으로 90도 회전해주기
def rotate(sticker, n, m):
result = list([0]*n for _ in range(m))
for i in range(n):
for j in range(m):
if sticker[i][j]: result[j][-(i+1)]=1
return result
# 노트북에 스티커 붙이기
def stickOn(y, x, laptop, sticker, n, m):
# 붙일 위치만 일단 저장
tmp = []
for i in range(n):
for j in range(m):
if ((sticker[i][j]==1) & (laptop[y+i][x+j]==0)):
tmp.append((y+i, x+j))
elif ((sticker[i][j]==1) & (laptop[y+i][x+j]==1)):
return False
# 위에서 return 안 걸렸다면, 스티커 붙이고 반환
for y, x in tmp:
laptop[y][x] = 1
return laptop
# 붙이기 시도
def trySticky(laptop, N, M, sticker, n, m):
# 회전은 총 4번
for _ in range(4):
# 모든 위치에서 스티커 붙이기 시도 (2단계)
for y in range(N):
for x in range(M):
if ((0 <= y+n <= N) & (0 <= x+m <= M)):
result = stickOn(y, x, laptop, sticker, n, m)
if result: return result
# 2단계 실패 시, 시계방향으로 돌려주고, 다시 2단계 반복 (3단계)
sticker = rotate(sticker, n, m)
# 회전하면서 스티커 가로세로가 바뀌니깐 바꿔준다.
n, m = m, n
# 스티커를 못 붙인다면 원래 노트북 그대로 반환
return laptop
if __name__ == '__main__':
N, M, K = map(int, input().split())
laptop = [[0]*M for _ in range(N)]
for _ in range(K):
n, m = map(int, input().split()) # 세로, 가로
sticker = [list(map(int, input().split())) for _ in range(n)]
laptop = trySticky(laptop, N, M, sticker, n, m)
answer = 0
for lap in laptop:
for l in lap:
answer += l
print(answer)
문제
혜윤이는 최근에 다양한 대회를 참여하면서 노트북에 붙일 수 있는 스티커들을 많이 받았다. 스티커는 아래와 같이 사각 모눈종이 위에 인쇄되어 있으며, 스티커의 각 칸은 상하좌우로 모두 연결되어 있다. 또한 모눈종이의 크기는 스티커의 크기에 꼭 맞아서, 상하좌우에 스티커가 포함되지 않는 불필요한 행이나 열이 존재하지 않는다.
아래는 올바른 모눈종이의 예시이다. 주황색 칸은 스티커가 붙은 칸을, 하얀색 칸은 스티커가 붙지 않은 칸을 나타낸다.
반면 아래는 올바르지 않은 모눈종이의 예시이다. 첫 번째는 윗쪽에 불필요한 행이 있고, 두 번째는 왼쪽에 불필요한 열이 있다. 그리고 세 번째는 스티커의 각 칸이 상하좌우로 모두 연결되어 있지 않다.
혜윤이는 자신의 노트북에 이 스티커들을 붙이기로 했다. 혜윤이의 노트북은 마침 직사각형 모양이고, 스티커가 인쇄된 모눈종이와 같은 간격으로 격자가 그려져 있다. 혜윤이는 스티커들을 먼저 받았던 것부터 차례대로 격자에 맞춰서 붙이려고 한다.
혜윤이가 스티커를 붙이는 방법은 다음과 같다.
스티커를 회전시키지 않고 모눈종이에서 떼어낸다.
다른 스티커와 겹치거나 노트북을 벗어나지 않으면서 스티커를 붙일 수 있는 위치를 찾는다. 혜윤이는 노트북의 위쪽부터 스티커를 채워 나가려고 해서, 스티커를 붙일 수 있는 위치가 여러 곳 있다면 가장 위쪽의 위치를 선택한다. 가장 위쪽에 해당하는 위치도 여러 곳이 있다면 그중에서 가장 왼쪽의 위치를 선택한다.
선택한 위치에 스티커를 붙인다. 만약 스티커를 붙일 수 있는 위치가 전혀 없어서 스티커를 붙이지 못했다면, 스티커를 시계 방향으로 90도 회전한 뒤 2번 과정을 반복한다.
위의 과정을 네 번 반복해서 스티커를 0도, 90도, 180도, 270도 회전시켜 봤음에도 스티커를 붙이지 못했다면 해당 스티커를 붙이지 않고 버린다.
아래의 예시를 통해 스티커를 붙이는 과정을 이해해보자. 노트북은 세로 5칸, 가로 4칸 크기이고, 혜윤이가 가지고 있는 스티커들은 아래와 같다. 왼쪽에서 오른쪽 순으로 스티커를 붙일 것이다.
첫 번째 스티커는 회전 없이 온전히 붙일 수 있는 공간이 아래와 같이 6곳이 있다.
이 중에서 가장 위쪽의 위치, 가능한 가장 위쪽의 위치가 여러 개이면 그 중에서 가장 왼쪽의 위치는 첫 번째이다. 스티커를 붙인 후 노트북의 모양은 아래와 같다.
두 번째 스티커는 회전 없이 온전히 붙일 수 있는 공간이 없다. 그러나 시계 방향으로 90도 회전한 후에는 붙일 수 있는 공간이 1개 생긴다. 해당 공간에 스티커를 붙인 후 노트북의 모양은 아래와 같다.
세 번째 스티커는 스티커를 시계방향으로 0, 90, 180, 270도 회전시킨 모양에 대해 전부 확인을 해도 스티커를 붙일 수 있는 공간이 없다. 그러므로 해당 스티커를 붙이지 않고 버린다.
네 번째 스티커는 스티커를 시계방향으로 0, 90, 180도 회전 시킨 모양에 대해 온전히 붙일 수 있는 공간이 없다. 그러나 시계 방향으로 270도 회전한 후에는 공간이 1개 생긴다. 스티커를 붙인 후 노트북의 모양은 아래와 같다. 최종적으로 노트북의 18칸이 스티커로 채워졌다.
혜윤이는 스티커를 다 붙인 후의 노트북의 모습이 궁금해졌다. 노트북의 크기와 스티커들이 주어졌을 때 스티커들을 차례대로 붙이고 난 후 노트북에서 몇 개의 칸이 채워졌는지 구해보자.
입력
첫째 줄에 노트북의 세로와 가로 길이를 나타내는 N(1 ≤ N ≤ 40)과 M(1 ≤ M ≤ 40), 그리고 스티커의 개수 K(1 ≤ K ≤ 100)이 한 칸의 빈칸을 사이에 두고 주어진다.
그 다음 줄부터는 K개의 스티커들에 대한 정보가 주어진다. 각 스티커는 아래와 같은 형식으로 주어진다.
먼저 i번째 스티커가 인쇄된 모눈종이의 행의 개수와 열의 개수를 나타내는 Ri(1 ≤ Ri ≤ 10)와 Ci(1 ≤ Ci ≤ 10)가 한 칸의 빈칸을 사이에 두고 주어진다.
다음 Ri개의 줄에는 각 줄마다 모눈종이의 각 행을 나타내는 Ci개의 정수가 한 개의 빈칸을 사이에 두고 주어진다. 각 칸에 들어가는 값은 0, 1이다. 0은 스티커가 붙지 않은 칸을, 1은 스티커가 붙은 칸을 의미한다.
문제에서 설명한 것과 같이 스티커는 모두 올바른 모눈종이에 인쇄되어 있다. 구체적으로 스티커의 각 칸은 상하좌우로 모두 연결되어 있고, 모눈종이의 크기는 스티커의 크기에 꼭 맞아서 상하좌우에 스티커에 전혀 포함되지 않는 불필요한 행이나 열이 존재하지 않는다.
출력
첫째 줄에 주어진 스티커들을 차례대로 붙였을 때 노트북에서 스티커가 붙은 칸의 수를 출력한다.
제한
예제 입력 1
복사
5 4 4
3 3
1 0 1
1 1 1
1 0 1
2 5
1 1 1 1 1
0 0 0 1 0
2 3
1 1 1
1 0 1
3 3
1 0 0
1 1 1
1 0 0
예제 출력 1
복사
18
예제 입력 2
복사
1 3 3
2 3
1 0 0
1 1 1
1 1
1
3 1
1
1
1
예제 출력 2
복사
1
예제 입력 3
복사
2 3 3
2 3
1 1 1
1 0 0
2 1
1
1
2 2
1 0
1 1
예제 출력 3
복사
6
예제 입력 4
복사
4 5 4
3 3
1 0 1
1 1 1
0 1 0
2 4
1 1 1 1
0 1 0 1
1 4
1 1 1 1
4 2
1 0
1 1
0 1
0 1
예제 출력 4
복사
17
예제 입력 5
복사
2 2 3
3 1
1
1
1
2 3
1 0 1
1 1 1
2 4
1 0 1 1
1 1 1 0
예제 출력 5
복사
0
예제 입력 6
복사
6 7 5
4 6
1 0 0 1 0 1
1 1 0 1 0 1
1 1 1 1 1 1
0 0 0 1 0 0
4 3
0 1 0
1 1 1
0 1 1
1 1 0
3 6
1 1 1 1 1 1
0 0 1 0 0 0
0 0 1 0 0 0
6 6
0 0 1 1 0 0
1 1 1 1 0 1
0 0 1 1 1 1
0 0 1 1 1 1
1 1 1 0 1 1
0 1 0 0 1 0
4 4
1 1 1 1
0 0 0 1
0 0 1 1
0 0 0 1
예제 출력 6
복사
30
예제 입력 7
복사
6 8 3
4 5
0 0 1 1 1
1 1 1 0 1
0 0 1 0 1
0 0 1 0 0
5 4
0 0 1 0
1 1 1 1
1 1 0 1
1 1 0 0
1 1 0 0
5 6
0 0 1 1 1 1
1 1 1 1 0 0
1 1 1 1 1 0
0 1 0 1 0 0
0 1 0 1 0 0
예제 출력 7
복사
22
예제 입력 8
복사
8 6 6
3 5
0 1 0 0 0
1 1 1 1 1
0 1 0 0 1
6 3
0 0 1
0 0 1
0 0 1
1 1 1
1 0 1
1 1 1
6 3
1 1 0
1 0 0
1 1 1
1 0 1
1 0 0
1 0 0
6 6
0 0 0 0 1 0
0 0 1 0 1 0
0 0 1 0 1 0
0 1 1 1 1 0
0 1 1 0 1 1
1 1 1 0 0 0
4 5
0 0 0 0 1
1 0 0 1 1
1 1 1 1 0
1 1 0 1 0
4 3
1 1 0
1 0 0
1 1 1
1 1 1
예제 출력 8
복사
29
힌트
-
부분합
출처 : 부분합
Solution
Python
import sys
input = sys.stdin.readline
if __name__ == '__main__':
N, S = map(int, input().split())
lst = list(map(int, input().split()))
# 투 포인터 / i, j < N
i, j = 0, 0
# 누적합 now
now = lst[i]
# 부분합 길이 초기 값
answer = N+1
while True:
# 합이 S 이상이면, 답 갱신(길이에 자신도 포함해야하니 +1)
if now >= S:
answer = min(answer, j-i+1)
# i를 한 칸 앞으로 옮기면서, 이전 i값은 빼줌
now -= lst[i]
i += 1
# i가 j보다 커지면 최소 n(1)이 구해진 것
if i > j: break
# 합이 S 미만이면 부분합 길이를 늘리기 위해 j+1
else:
j += 1
# j 가 N보다 작을 때는, now에 j 위치 값만큼 더해준다.
if j < N: now += lst[j]
# j가 N 이상이라면, 더이상 부분합으로 S 이상 못 만든다는 것
else: break
# 초기값 그대로라면 0, 아니면 answer
answer = answer if answer != (N+1) else 0
print(answer)
문제
10,000 이하의 자연수로 이루어진 길이 N짜리 수열이 주어진다. 이 수열에서 연속된 수들의 부분합 중에 그 합이 S 이상이 되는 것 중, 가장 짧은 것의 길이를 구하는 프로그램을 작성하시오.
입력
첫째 줄에 N (10 ≤ N < 100,000)과 S (0 < S ≤ 100,000,000)가 주어진다. 둘째 줄에는 수열이 주어진다. 수열의 각 원소는 공백으로 구분되어져 있으며, 10,000이하의 자연수이다.
출력
첫째 줄에 구하고자 하는 최소의 길이를 출력한다. 만일 그러한 합을 만드는 것이 불가능하다면 0을 출력하면 된다.
제한
예제 입력 1
복사
10 15
5 1 3 5 10 7 4 9 2 8
예제 출력 1
복사
2
힌트
W3sicHJvYmxlbV9pZCI6IjE4MDYiLCJwcm9ibGVtX2xhbmciOiIwIiwidGl0bGUiOiJcdWJkODBcdWJkODRcdWQ1NjkiLCJkZXNjcmlwdGlvbiI6IjxwPjEwLDAwMCBcdWM3NzRcdWQ1NThcdWM3NTggXHVjNzkwXHVjNWYwXHVjMjE4XHViODVjIFx1Yzc3NFx1YjhlOFx1YzViNFx1YzljNCBcdWFlMzhcdWM3NzQgTlx1YzlkY1x1YjlhYyBcdWMyMThcdWM1ZjRcdWM3NzQgXHVjOGZjXHVjNWI0XHVjOWM0XHViMmU0LiBcdWM3NzQgXHVjMjE4XHVjNWY0XHVjNWQwXHVjMTFjIFx1YzVmMFx1YzE4ZFx1YjQxYyBcdWMyMThcdWI0ZTRcdWM3NTggXHViZDgwXHViZDg0XHVkNTY5IFx1YzkxMVx1YzVkMCBcdWFkZjggXHVkNTY5XHVjNzc0IFMgXHVjNzc0XHVjMGMxXHVjNzc0IFx1YjQxOFx1YjI5NCBcdWFjODMgXHVjOTExLCBcdWFjMDBcdWM3YTUgXHVjOWU3XHVjNzQwIFx1YWM4M1x1Yzc1OCBcdWFlMzhcdWM3NzRcdWI5N2MgXHVhZDZjXHVkNTU4XHViMjk0IFx1ZDUwNFx1Yjg1Y1x1YWRmOFx1YjdhOFx1Yzc0NCBcdWM3OTFcdWMxMzFcdWQ1NThcdWMyZGNcdWM2MjQuPFwvcD5cclxuIiwiaW5wdXQiOiI8cD5cdWNjYWJcdWM5ZjggXHVjOTA0XHVjNWQwIE4gKDEwICZsZTsgTiAmbHQ7IDEwMCwwMDApXHVhY2ZjIFMgKDAgJmx0OyBTICZsZTsgMTAwLDAwMCwwMDApXHVhYzAwIFx1YzhmY1x1YzViNFx1YzljNFx1YjJlNC4gXHViNDU4XHVjOWY4IFx1YzkwNFx1YzVkMFx1YjI5NCBcdWMyMThcdWM1ZjRcdWM3NzQgXHVjOGZjXHVjNWI0XHVjOWM0XHViMmU0LiBcdWMyMThcdWM1ZjRcdWM3NTggXHVhYzAxIFx1YzZkMFx1YzE4Y1x1YjI5NCBcdWFjZjVcdWJjMzFcdWM3M2NcdWI4NWMgXHVhZDZjXHViZDg0XHViNDE4XHVjNWI0XHVjODM4IFx1Yzc4OFx1YzczY1x1YmE3MCwgMTAsMDAwXHVjNzc0XHVkNTU4XHVjNzU4IFx1Yzc5MFx1YzVmMFx1YzIxOFx1Yzc3NFx1YjJlNC48XC9wPlxyXG4iLCJvdXRwdXQiOiI8cD5cdWNjYWJcdWM5ZjggXHVjOTA0XHVjNWQwIFx1YWQ2Y1x1ZDU1OFx1YWNlMFx1Yzc5MCBcdWQ1NThcdWIyOTQgXHVjZDVjXHVjMThjXHVjNzU4IFx1YWUzOFx1Yzc3NFx1Yjk3YyBcdWNkOWNcdWI4MjVcdWQ1NWNcdWIyZTQuIFx1YjljY1x1Yzc3YyBcdWFkZjhcdWI3ZWNcdWQ1NWMgXHVkNTY5XHVjNzQ0IFx1YjljY1x1YjRkY1x1YjI5NCBcdWFjODNcdWM3NzQgXHViZDg4XHVhYzAwXHViMmE1XHVkNTU4XHViMmU0XHViYTc0IDBcdWM3NDQgXHVjZDljXHViODI1XHVkNTU4XHViYTc0IFx1YjQxY1x1YjJlNC48XC9wPlxyXG4iLCJoaW50IjoiIiwib3JpZ2luYWwiOiIwIiwiaHRtbF90aXRsZSI6IjAiLCJwcm9ibGVtX2xhbmdfdGNvZGUiOiJLb3JlYW4ifSx7InByb2JsZW1faWQiOiIxODA2IiwicHJvYmxlbV9sYW5nIjoiMSIsInRpdGxlIjoiU3Vic2VxdWVuY2UiLCJkZXNjcmlwdGlvbiI6IjxwPkEgc2VxdWVuY2Ugb2YgTiBwb3NpdGl2ZSBpbnRlZ2VycyAoMTAgJmxlOyBOICZsdDsgMTAwIDAwMCksIGVhY2ggb2YgdGhlbSBsZXNzIHRoYW4gb3IgZXF1YWwgMTAwMDAsIGFuZCBhIHBvc2l0aXZlIGludGVnZXIgUyAoUyAmbGU7IDEwMCAwMDAgMDAwKSBhcmUgZ2l2ZW4uIFdyaXRlIGEgcHJvZ3JhbSB0byBmaW5kIHRoZSBtaW5pbWFsIGxlbmd0aCBvZiB0aGUgc3Vic2VxdWVuY2Ugb2YgY29uc2VjdXRpdmUgZWxlbWVudHMgb2YgdGhlIHNlcXVlbmNlLCB0aGUgc3VtIG9mIHdoaWNoIGlzIGdyZWF0ZXIgdGhhbiBvciBlcXVhbCB0byBTLiZuYnNwOzxcL3A+XHJcbiIsImlucHV0IjoiPHA+TWFueSB0ZXN0IGNhc2VzIHdpbGwgYmUgZ2l2ZW4uIEZvciBlYWNoIHRlc3QgY2FzZSB0aGUgcHJvZ3JhbSBoYXMgdG8gcmVhZCB0aGUgbnVtYmVycyBOIGFuZCBTLCBzZXBhcmF0ZWQgYnkgYW4gaW50ZXJ2YWwsIGZyb20gdGhlIGZpcnN0IGxpbmUuIFRoZSBudW1iZXJzIG9mIHRoZSBzZXF1ZW5jZSBhcmUgZ2l2ZW4gaW4gdGhlIHNlY29uZCBsaW5lIG9mIHRoZSB0ZXN0IGNhc2UsIHNlcGFyYXRlZCBieSBpbnRlcnZhbHMuIFRoZSBpbnB1dCB3aWxsIGZpbmlzaCB3aXRoIHRoZSBlbmQgb2YgZmlsZS48XC9wPlxyXG4iLCJvdXRwdXQiOiI8cD5Gb3IgZWFjaCB0aGUgY2FzZSB0aGUgcHJvZ3JhbSBoYXMgdG8gcHJpbnQgdGhlIHJlc3VsdCBvbiBzZXBhcmF0ZSBsaW5lIG9mIHRoZSBvdXRwdXQgZmlsZS4gSWYgaXQgaXMgaW1wb3NzaWJsZSB0byBtYWtlIHN1Y2ggYSBzdW0sIHByaW50IHplcm8uPFwvcD5cclxuIiwiaGludCI6IiIsIm9yaWdpbmFsIjoiMSIsImh0bWxfdGl0bGUiOiIwIiwicHJvYmxlbV9sYW5nX3Rjb2RlIjoiRW5nbGlzaCJ9XQ==
-
찾기
출처 : 찾기
Solution
Python
import sys
input = sys.stdin.readline
# 파이배열 : 문자열에서 패턴을 찾고,
# 접두사와 접미사가 해당 위치에서 몇번째까지 같은지 찾는 알고리즘
def piList(pattern):
n = len(pattern)
# 파이배열 초기화
pi = [0]*n
# i=전체에서 시작위치, j=현재 체크해야할 마지막 위치
i = 0
for j in range(1, n):
# 만약 다를 경우, i가 0이 될 때까지 초기화
# 초기화는 파이배열에서 이전까지의 반복위치 값을 찾아가며 초기화해준다.
# 만약 i번째 문자와 j번째 문자가 같다면, 그 순간부터는 다음 값을 비교해준다.
while i > 0 and pattern[i] != pattern[j]:
i = pi[i-1]
# 같으면, i를 1더하고 파이배열에 이전까지의 값은 동일했음을 저장
if pattern[i] == pattern[j]:
i += 1
pi[j]=i
# 만들어진 파이배열 리턴
return pi
def KMP(T, P):
n, m = len(T), len(P)
# 먼저 파이배열을 만들어서 패턴을 찾는다.
pi = piList(P)
# 결과가 저장될 배열
res = []
# i=P에서 체크해야하는 값이 있는 위치, j=T에서 체크해야하는 위치
i = 0
for j in range(n):
# 서로 다르다면, 파이배열 찾을 때와 동일하게 진행
# 같은 문자가 나올 때까지 P에서 비교하는 문자를 하나씩 이전까지 같았던 값으로 변경
while i > 0 and P[i] != T[j]:
i = pi[i-1]
# 서로 같을 경우, P에서 비교하는 문자를 하나씩 더해줌(j는 for문으로 인해 계속 +1 됨)
if P[i] == T[j]:
i += 1
# 만약 P를 끝까지 체크했다면, res에 저장하고 해당위치에서 동일문자가 있던 위치까지 이동
if i == m:
res.append(j-i+1)
i = pi[i-1]
return res
if __name__ == '__main__':
# strip을 하면 문장 시작이 공백으로 시작할 경우 사라져버림 > rstrip으로!
T = '0' + input().rstrip()
P = input().rstrip()
ans = KMP(T, P)
# 출력
print(len(ans))
for a in ans:
print(a, end=' ')
#############################################################
# 해당 방식은 예상했지만 시간 초과임
'''
if __name__ == '__main__':
T = input().strip()
P = input().strip()
ansN = 0
ansIdx = []
while True:
ans = T.find(P)
# -1일 경우, T 안에서 P를 찾지 못한다.
if ans==-1: break
# 위치를 찾았다면 해당 위치를 저장
ansN += 1
# 저장은 가장 마지막 값에서 찾은 인덱스 값을 더해서 진행
if ansIdx: ansIdx.append(ansIdx[-1]+ans+1)
# 처음이라면 1을 더해서 저장
else: ansIdx.append(ans+1)
# 자르고 다시 체크
T = T[ans+1:]
# 출력
print(ansN)
for n in ansIdx:
print(n, end=' ')
'''
문제
워드프로세서 등을 사용하는 도중에 찾기 기능을 이용해 본 일이 있을 것이다. 이 기능을 여러분이 실제로 구현해 보도록 하자.
두 개의 문자열 P와 T에 대해, 문자열 P가 문자열 T 중간에 몇 번, 어느 위치에서 나타나는지 알아내는 문제를 '문자열 매칭'이라고 한다. 워드프로세서의 찾기 기능은 이 문자열 매칭 문제를 풀어주는 기능이라고 할 수 있다. 이때의 P는 패턴이라고 부르고 T는 텍스트라고 부른다.
편의상 T의 길이를 n, P의 길이를 m이라고 하자. 일반적으로, n ≥ m이라고 가정해도 무리가 없다. n<m이면 어차피 P는 T중간에 나타날 수 없기 때문이다. 또, T의 i번째 문자를 T[i]라고 표현하도록 하자. 그러면 물론, P의 i번째 문자는 P[i]라고 표현된다.
1 2 3 4 5 6 7 8 9 …
T : [ A B C D A B C D A B D E ]
| | | | | | X
P : [ A B C D A B D ]
1 2 3 4 5 6 7
문자열 P가 문자열 T 중간에 나타난다는 것, 즉 문자열 P가 문자열 T와 매칭을 이룬다는 것이 어떤 것인지 위와 아래의 두 예를 통해 알아보자. 위의 예에서 P는, T의 1번 문자에서 시작하는 매칭에 실패했다. T의 7번 문자 T[7]과, P의 7번 문자 P[7]이 서로 다르기 때문이다.
그러나 아래의 예에서 P는, T의 5번 문자에서 시작하는 매칭에 성공했다. T의 5~11번 문자와 P의 1~7번 문자가 서로 하나씩 대응되기 때문이다.
1 2 3 4 5 6 7 8 9 …
T : [ A B C D A B C D A B D E ]
| | | | | | |
P : [ A B C D A B D ]
1 2 3 4 5 6 7
가장 단순한 방법으로, 존재하는 모든 매칭을 확인한다면, 시간복잡도가 어떻게 될까? T의 1번 문자에서 시작하는 매칭이 가능한지 알아보기 위해서, T의 1~m번 문자와 P의 1~m번 문자를 비교한다면 최대 m번의 연산이 필요하다. 이 비교들이 끝난 후, T의 2번 문자에서 시작하는 매칭이 가능한지 알아보기 위해서, T의 2~m+1번 문자와 P의 1~m번 문자를 비교한다면 다시 최대 m번의 연산이 수행된다. 매칭은 T의 n-m+1번 문자에서까지 시작할 수 있으므로, 이러한 방식으로 진행한다면 O( (n-m+1) × m ) = O(nm) 의 시간복잡도를 갖는 알고리즘이 된다.
더 좋은 방법은 없을까? 물론 있다. 위에 제시된 예에서, T[7] ≠ P[7] 이므로 T의 1번 문자에서 시작하는 매칭이 실패임을 알게 된 순간으로 돌아가자. 이때 우리는 매칭이 실패라는 사실에서, T[7] ≠ P[7] 라는 정보만을 얻은 것이 아니다. 오히려 i=1…6에 대해 T[i] = P[i] 라고 하는 귀중한 정보를 얻지 않았는가? 이 정보를 십분 활용하면, O(n)의 시간복잡도 내에 문자열 매칭 문제를 풀어내는 알고리즘을 설계할 수 있다.
P 내부에 존재하는 문자열의 반복에 주목하자. P에서 1, 2번 문자 A, B는 5, 6번 문자로 반복되어 나타난다. 또, T의 1번 문자에서 시작하는 매칭이 7번 문자에서야 실패했으므로 T의 5, 6번 문자도 A, B이다.
따라서 T의 1번 문자에서 시작하는 매칭이 실패한 이후, 그 다음으로 가능한 매칭은 T의 5번 문자에서 시작하는 매칭임을 알 수 있다! 더불어, T의 5~6번 문자는 P의 1~2번 문자와 비교하지 않아도, 서로 같다는 것을 이미 알고 있다! 그러므로 이제는 T의 7번 문자와 P의 3번 문자부터 비교해 나가면 된다.
이제 이 방법을 일반화 해 보자. T의 i번 문자에서 시작하는 매칭을 검사하던 중 T[i+j-1] ≠ P[j]임을 발견했다고 하자. 이렇게 P의 j번 문자에서 매칭이 실패한 경우, P[1…k] = P[j-k…j-1]을 만족하는 최대의 k(≠j-1)에 대해 T의 i+j-1번 문자와 P의 k+1번 문자부터 비교를 계속해 나가면 된다.
이 최대의 k를 j에 대한 함수라고 생각하고, 1~m까지의 각 j값에 대해 최대의 k를 미리 계산해 놓으면 편리할 것이다. 이를 전처리 과정이라고 부르며, O(m)에 완료할 수 있다.
이러한 원리를 이용하여, T와 P가 주어졌을 때, 문자열 매칭 문제를 해결하는 프로그램을 작성하시오.
입력
첫째 줄에 문자열 T가, 둘째 줄에 문자열 P가 주어진다. T와 P의 길이 n, m은 1이상 100만 이하이고, 알파벳 대소문자와 공백으로만 이루어져 있다.
출력
첫째 줄에, T 중간에 P가 몇 번 나타나는지를 나타내는 음이 아닌 정수를 출력한다. 둘째 줄에는 P가 나타나는 위치를 차례대로 공백으로 구분해 출력한다. 예컨대, T의 i~i+m-1번 문자와 P의 1~m번 문자가 차례로 일치한다면, i를 출력하는 식이다.
제한
예제 입력 1
복사
ABC ABCDAB ABCDABCDABDE
ABCDABD
예제 출력 1
복사
1
16
힌트
-
최단경로
출처 : 최단경로
Solution
Python
import sys
input = sys.stdin.readline
import heapq
if __name__ == '__main__':
V, E = map(int, input().split())
K = int(input())
Edges = [[] for _ in range(V+1)]
# 간선에 대해 입력받고 Edges에 (가중치, 연결 노드) 순으로 저장
for _ in range(E):
u, v, w = map(int, input().split())
Edges[u].append((w, v))
# K에서 각 정점까지 거리 저장 배열
answer = [float('inf')] * (V+1)
answer[K] = 0
# deque 쓰면 시간초과 나옴 > heapq 사용!
HQ = []
heapq.heappush(HQ, (0, K))
while HQ:
cnt, now = heapq.heappop(HQ)
# 누적합이 최소 가중치보다 크면 체크 안함
if answer[now] < cnt: continue
# 현재 연결된 모든 정점들 체크
for w, v in Edges[now]:
new_w = cnt+w
# 연결된 정점의 최소 가중치가 갱신가능할 때만 이동
if new_w < answer[v]:
answer[v] = new_w
heapq.heappush(HQ, (new_w, v))
# 정답 출력
for ans in answer[1:]:
if ans==float('inf'): print('INF')
else: print(ans)
문제
방향그래프가 주어지면 주어진 시작점에서 다른 모든 정점으로의 최단 경로를 구하는 프로그램을 작성하시오. 단, 모든 간선의 가중치는 10 이하의 자연수이다.
입력
첫째 줄에 정점의 개수 V와 간선의 개수 E가 주어진다. (1 ≤ V ≤ 20,000, 1 ≤ E ≤ 300,000) 모든 정점에는 1부터 V까지 번호가 매겨져 있다고 가정한다. 둘째 줄에는 시작 정점의 번호 K(1 ≤ K ≤ V)가 주어진다. 셋째 줄부터 E개의 줄에 걸쳐 각 간선을 나타내는 세 개의 정수 (u, v, w)가 순서대로 주어진다. 이는 u에서 v로 가는 가중치 w인 간선이 존재한다는 뜻이다. u와 v는 서로 다르며 w는 10 이하의 자연수이다. 서로 다른 두 정점 사이에 여러 개의 간선이 존재할 수도 있음에 유의한다.
출력
첫째 줄부터 V개의 줄에 걸쳐, i번째 줄에 i번 정점으로의 최단 경로의 경로값을 출력한다. 시작점 자신은 0으로 출력하고, 경로가 존재하지 않는 경우에는 INF를 출력하면 된다.
제한
예제 입력 1
복사
5 6
1
5 1 1
1 2 2
1 3 3
2 3 4
2 4 5
3 4 6
예제 출력 1
복사
0
2
3
7
INF
힌트
-
나는야 포켓몬 마스터 이다솜
출처 : 나는야 포켓몬 마스터 이다솜
Solution
Python
import sys
input = sys.stdin.readline
if __name__ == '__main__':
N, M = map(int, input().split())
# 하나씩 dict 형태로 입력받는다.
lib = dict()
for i in range(1, N+1):
lib[i] = input().rstrip()
# 생성된 lib의 키, 값 반전
rlib = {v:k for k,v in lib.items()}
# 문제 입력받고, 바로 답 출력
for _ in range(M):
q = input().rstrip()
if q[0] in '123456789':
q = int(q)
print(lib[q])
else:
print(rlib[q])
문제
안녕? 내 이름은 이다솜. 나의 꿈은 포켓몬 마스터야. 일단 포켓몬 마스터가 되기 위해선 포켓몬을 한 마리 잡아야겠지? 근처 숲으로 가야겠어.
(뚜벅 뚜벅)
얏! 꼬렛이다. 꼬렛? 귀여운데, 나의 첫 포켓몬으로 딱 어울린데? 내가 잡고 말겠어. 가라! 몬스터볼~
(펑!) 헐랭... 왜 안 잡히지?ㅜㅜ 몬스터 볼만 던지면 되는 게 아닌가...ㅜㅠ
(터벅터벅)
어? 누구지?
오박사 : 나는 태초마을의 포켓몬 박사 오민식 박사라네. 다솜아, 포켓몬을 잡을 때는, 일단 상대 포켓몬의 체력을 적당히 바닥으로 만들어놓고 몬스터 볼을 던져야 한단다. 자, 내 포켓몬 이상해꽃으로 한번 잡아보렴. 포켓몬의 기술을 쓰는 것을 보고 포켓몬을 줄지 안줄지 결정을 하겠네. 자 한번 해보아라. 다솜아.
이다솜 : 이상해꽃이라...음.. 꽃이니깐 왠지 햇빛을 받아서 공격을 할 것 같은데... 음... 이상해꽃! 햇빛공격!!!
(꼬렛이 이상해꽃에게 공격을 받아 체력이 25 감소했다.) 가라! 몬스터 볼!!! (꼬렛을 잡았습니다.) 야호! 신난다. 꼬렛을 잡았다.
오박사 : 오우!! 방금 쓴 공격은 솔라빔이라고 하네.. 어떻게 공격을 한 건가? 솔라빔이란 공격에 대해서 공부를 한 건가?
이다솜 : 꽃이니깐 왠지 햇빛을 제대로 받으면 광합성을 해서 음.. 그냥 그럴 것 같아서요 ☞☜
오박사 : 다른 아이들은 넝쿨채찍이나, 나뭇잎 공격을 하는데, 다솜이는 역시 뭔가 다르구나. 그럼 나와 함께 연구소로 가자꾸나. 내가 포켓몬을 한 마리 줄 테니, 너의 꿈을 펼쳐보아라. 꿈은 이루어진단다.
이다솜 : 네! 오박사님, 고마워요.ㅜㅜ
오박사 : 가자. 나의 연구소는 너의 옆집의 아랫집이란다. 같이 가도록하자. 지금 포켓몬을 주마.
이다솜 : 네. 야호!!
'
오영식 : 어? 오박사님 얘는 누구인가요?
오박사 : 얘는 너의 라이벌이 될 친구 이다솜이라고 하네. 자, 포켓몬을 한 마리 골라보도록 해봐라 다솜아. 레이디퍼스트 네가 먼저 골라봐라.
이다솜 : 저는 생각해둔 포켓몬이 있어요. 피카츄 골라도 될까요?
오박사 : 그래 여기 피카츄가 한 마리 있단다. 피카츄를 가져가거라.
오영식 : 그럼 저는 이브이를 가져가겠어요. 그럼 나중에 보자 이다솜.
이다솜 : 그럼 꼬렛을 다시 잡으러 가야겠다. 영식아, 그리고 민식박사님 빠잉!
이다솜 : 피카츄 공격!
가라 몬스터 볼!
이다솜 : 야호! 신난다. 꼬렛을 잡았다!!!!!
이다솜 : 그럼! 일단 사천왕을 이기고 오겠어!
이다솜 : 여기가 사천왕과 대결하려면 가야하는 곳인가..
경비원 : 사천왕과 대결을 하려면, 마을의 체육관 리더를 이겨서 배지를 8개를 모아야 한다네... 배지를 모아서 오도록 하게
이다솜 : 잉ㅠㅜ... 그럼 배지부터 모아야 하는구나ㅠㅜㅠㅜ 나쁘당 그냥 좀 봐주지..
<1 년 후>
그동안의 줄거리 : 이다솜은 일단 상록 숲의 체육관 리더에게 도전을 했다. 하지만 상록숲 체육관의 리더는 실종된 상태. 따라서 회색마을부터 도전하기로 했다. 체육관의 리더를 이기면서, 로켓단을 해체시키기도 하고, 여러 가지 사건도 있었다. 결국 전설의 포켓몬도 잡고, 이제 사천왕을 이기려고 도전하기로 했다. 사천왕은 모두 가볍게 이기고, 이제 마지막 라이벌 오!영!식! 이다.
오영식 : 훗. 1년 전의 그 이다솜이 사천왕을 이기고 현재 포켓몬 마스터인 나에게 덤벼? 어디 한번 덤벼보시지.
이다솜 : 헐랭... 나를 우습게보네.... 한번 두고 보시지! 그럼 대결이닷!
이다솜 : 휴... 이겼다.
오영식 : 내가 지다니 분하다. ㅜㅜ
오박사 : 그럼 다솜아 이제 진정한 포켓몬 마스터가 되기 위해 도감을 완성시키도록 하여라. 일단 네가 현재 가지고 있는 포켓몬 도감에서 포켓몬의 이름을 보면 포켓몬의 번호를 말하거나, 포켓몬의 번호를 보면 포켓몬의 이름을 말하는 연습을 하도록 하여라. 나의 시험을 통과하면, 내가 새로 만든 도감을 주도록 하겠네.
입력
첫째 줄에는 도감에 수록되어 있는 포켓몬의 개수 N이랑 내가 맞춰야 하는 문제의 개수 M이 주어져. N과 M은 1보다 크거나 같고, 100,000보다 작거나 같은 자연수인데, 자연수가 뭔지는 알지? 모르면 물어봐도 괜찮아. 나는 언제든지 질문에 답해줄 준비가 되어있어.
둘째 줄부터 N개의 줄에 포켓몬의 번호가 1번인 포켓몬부터 N번에 해당하는 포켓몬까지 한 줄에 하나씩 입력으로 들어와. 포켓몬의 이름은 모두 영어로만 이루어져있고, 또, 음... 첫 글자만 대문자이고, 나머지 문자는 소문자로만 이루어져 있어. 아참! 일부 포켓몬은 마지막 문자만 대문자일 수도 있어. 포켓몬 이름의 최대 길이는 20, 최소 길이는 2야. 그 다음 줄부터 총 M개의 줄에 내가 맞춰야하는 문제가 입력으로 들어와. 문제가 알파벳으로만 들어오면 포켓몬 번호를 말해야 하고, 숫자로만 들어오면, 포켓몬 번호에 해당하는 문자를 출력해야해. 입력으로 들어오는 숫자는 반드시 1보다 크거나 같고, N보다 작거나 같고, 입력으로 들어오는 문자는 반드시 도감에 있는 포켓몬의 이름만 주어져. 그럼 화이팅!!!
출력
첫째 줄부터 차례대로 M개의 줄에 각각의 문제에 대한 답을 말해줬으면 좋겠어!!!. 입력으로 숫자가 들어왔다면 그 숫자에 해당하는 포켓몬의 이름을, 문자가 들어왔으면 그 포켓몬의 이름에 해당하는 번호를 출력하면 돼. 그럼 땡큐~
이게 오박사님이 나에게 새로 주시려고 하는 도감이야. 너무 가지고 싶다ㅠㅜ. 꼭 만점을 받아줬으면 좋겠어!! 파이팅!!!
제한
예제 입력 1
복사
26 5
Bulbasaur
Ivysaur
Venusaur
Charmander
Charmeleon
Charizard
Squirtle
Wartortle
Blastoise
Caterpie
Metapod
Butterfree
Weedle
Kakuna
Beedrill
Pidgey
Pidgeotto
Pidgeot
Rattata
Raticate
Spearow
Fearow
Ekans
Arbok
Pikachu
Raichu
25
Raichu
3
Pidgey
Kakuna
예제 출력 1
복사
Pikachu
26
Venusaur
16
14
힌트
-
치킨 배달
출처 : 치킨 배달
Solution
Python
import sys
input = sys.stdin.readline
from itertools import combinations
if __name__ == '__main__':
N, M = map(int, input().split())
house = []
chicken = []
for y in range(N):
lst = list(map(int, input().split()))
for x in range(N):
if lst[x] == 1:
house.append((y,x))
elif lst[x] == 2:
chicken.append((y,x))
# [i][j] : i=chicken수 / j=house수
c, h = len(chicken), len(house)
chDir = [[0]*h for _ in range(c)]
# 각 집과 치킨집 간의 "치킨 거리" 계산
for i in range(c):
for j in range(h):
chDir[i][j] = abs(chicken[i][0]-house[j][0]) + abs(chicken[i][1]-house[j][1])
# 최종 정답 변수
answer = float('inf')
# M개만큼 선택하는 치킨집 위치 사수
for combi in combinations(range(c), M):
# 현재 조합에서 최소가 되는 치킨 거리 저장
ans = 0
# 현재 집 위치 선택
for k in range(h):
# 현재 집에서 치킨집까지 위치 중 가장 짧은 거리
now = float('inf')
for chk in combi:
now = min(now, chDir[chk][k])
ans += now
answer = min(answer, ans)
print(answer)
문제
크기가 N×N인 도시가 있다. 도시는 1×1크기의 칸으로 나누어져 있다. 도시의 각 칸은 빈 칸, 치킨집, 집 중 하나이다. 도시의 칸은 (r, c)와 같은 형태로 나타내고, r행 c열 또는 위에서부터 r번째 칸, 왼쪽에서부터 c번째 칸을 의미한다. r과 c는 1부터 시작한다.
이 도시에 사는 사람들은 치킨을 매우 좋아한다. 따라서, 사람들은 "치킨 거리"라는 말을 주로 사용한다. 치킨 거리는 집과 가장 가까운 치킨집 사이의 거리이다. 즉, 치킨 거리는 집을 기준으로 정해지며, 각각의 집은 치킨 거리를 가지고 있다. 도시의 치킨 거리는 모든 집의 치킨 거리의 합이다.
임의의 두 칸 (r1, c1)과 (r2, c2) 사이의 거리는 |r1-r2| + |c1-c2|로 구한다.
예를 들어, 아래와 같은 지도를 갖는 도시를 살펴보자.
0 2 0 1 0
1 0 1 0 0
0 0 0 0 0
0 0 0 1 1
0 0 0 1 2
0은 빈 칸, 1은 집, 2는 치킨집이다.
(2, 1)에 있는 집과 (1, 2)에 있는 치킨집과의 거리는 |2-1| + |1-2| = 2, (5, 5)에 있는 치킨집과의 거리는 |2-5| + |1-5| = 7이다. 따라서, (2, 1)에 있는 집의 치킨 거리는 2이다.
(5, 4)에 있는 집과 (1, 2)에 있는 치킨집과의 거리는 |5-1| + |4-2| = 6, (5, 5)에 있는 치킨집과의 거리는 |5-5| + |4-5| = 1이다. 따라서, (5, 4)에 있는 집의 치킨 거리는 1이다.
이 도시에 있는 치킨집은 모두 같은 프랜차이즈이다. 프렌차이즈 본사에서는 수익을 증가시키기 위해 일부 치킨집을 폐업시키려고 한다. 오랜 연구 끝에 이 도시에서 가장 수익을 많이 낼 수 있는 치킨집의 개수는 최대 M개라는 사실을 알아내었다.
도시에 있는 치킨집 중에서 최대 M개를 고르고, 나머지 치킨집은 모두 폐업시켜야 한다. 어떻게 고르면, 도시의 치킨 거리가 가장 작게 될지 구하는 프로그램을 작성하시오.
입력
첫째 줄에 N(2 ≤ N ≤ 50)과 M(1 ≤ M ≤ 13)이 주어진다.
둘째 줄부터 N개의 줄에는 도시의 정보가 주어진다.
도시의 정보는 0, 1, 2로 이루어져 있고, 0은 빈 칸, 1은 집, 2는 치킨집을 의미한다. 집의 개수는 2N개를 넘지 않으며, 적어도 1개는 존재한다. 치킨집의 개수는 M보다 크거나 같고, 13보다 작거나 같다.
출력
첫째 줄에 폐업시키지 않을 치킨집을 최대 M개를 골랐을 때, 도시의 치킨 거리의 최솟값을 출력한다.
제한
예제 입력 1
복사
5 3
0 0 1 0 0
0 0 2 0 1
0 1 2 0 0
0 0 1 0 0
0 0 0 0 2
예제 출력 1
복사
5
예제 입력 2
복사
5 2
0 2 0 1 0
1 0 1 0 0
0 0 0 0 0
2 0 0 1 1
2 2 0 1 2
예제 출력 2
복사
10
예제 입력 3
복사
5 1
1 2 0 0 0
1 2 0 0 0
1 2 0 0 0
1 2 0 0 0
1 2 0 0 0
예제 출력 3
복사
11
예제 입력 4
복사
5 1
1 2 0 2 1
1 2 0 2 1
1 2 0 2 1
1 2 0 2 1
1 2 0 2 1
예제 출력 4
복사
32
힌트
-
거의 소수
출처 : 거의 소수
Solution
Python
import sys
input = sys.stdin.readline
'''
1. 소수인지 확인 (에라토스테네스의 체로 소수 먼저 구하기)
2. 소수라면 계속 곱하면서 나오는 거의 소수들 체크
3. 거의 소수는 pass, 소수 아닌건 넘김
4. 최종 거의 소수 갯수 출력
'''
# 에라토스테네스의 체
def Eratos(B):
# B의 제곱근까지만 소수인지 체크해도 됨
l = int(B**(1/2))+1
lst = [True]*l
prime = []
for n in range(2, l):
if lst[n]:
c = 2
while (n*c) < l:
lst[n*c] = False
c += 1
prime.append(n)
return prime
# 단순히 n제곱하며 A 이상 B 이하인 수를 센다.
def almostPrime(A, B, prime):
answer = 0
for n in prime:
i = 2
while True:
k = n**i
if k > B: break
if (A <= k <= B):
answer += 1
i += 1
return answer
if __name__ == '__main__':
A, B = map(int, input().split())
prime = Eratos(B)
answer = almostPrime(A, B, prime)
print(answer)
문제
어떤 수가 소수의 N제곱(N ≥ 2) 꼴일 때, 그 수를 거의 소수라고 한다.
두 정수 A와 B가 주어지면, A보다 크거나 같고, B보다 작거나 같은 거의 소수가 몇 개인지 출력한다.
입력
첫째 줄에 왼쪽 범위 A와 오른쪽 범위 B가 공백 한 칸을 사이에 두고 주어진다.
출력
첫째 줄에 총 몇 개가 있는지 출력한다.
제한
1 ≤ A ≤ B ≤ 1014
예제 입력 1
복사
1 1000
예제 출력 1
복사
25
예제 입력 2
복사
1 10
예제 출력 2
복사
3
예제 입력 3
복사
5324 894739
예제 출력 3
복사
183
힌트
-
구슬 탈출 2
출처 : 구슬 탈출 2
Solution
C
#define _CRT_SECURE_NO_WARNINGS
typedef struct Node {
int Rx, Ry, Bx, By;
int count;
char flag; //h==head(start), u==up, d==down, l==left, r==right, c==cannot move, t==tail(end)
struct Node* next;
}Node;
int result = 11;
void init(char** Board, int N, int M, Node* Ball) {
for (int i = 0; i < N; i++) {
for (int j = 0; j < M; j++) {
if (Board[i][j] == 'R') {
Ball->Ry = i;
Ball->Rx = j;
Board[i][j] = '.';
}
else if (Board[i][j] == 'B') {
Ball->By = i;
Ball->Bx = j;
Board[i][j] = '.';
}
}
}
Ball->count = 0;
Ball->flag = 'h';
Ball->next = NULL;
}
Node* create(Node* prev) {
Node* next;
next = (Node*)malloc(sizeof(Node));
next->Rx = prev->Rx;
next->Ry = prev->Ry;
next->Bx = prev->Bx;
next->By = prev->By;
next->count = prev->count + 1;
prev->next = next;
return(next);
}
void delete(Node* top) {
Node* tmp;
tmp = top;
top = top->next;
free(tmp);
}
void check_the_way(char** Board, Node* Ball);
void up(char** Board, Node* Ball) {
int R = 1, B = 1;
int c = 0;
Node* top = create(Ball);
while (R == 1 || B == 1) {
if (Board[top->Ry - 1][top->Rx] == '#' || (top->Ry - 1 == top->By && top->Rx == top->Bx))
R = 0;
if (Board[top->By - 1][top->Bx] == '#' || (top->By - 1 == top->Ry && top->Bx == top->Rx))
B = 0;
if (R == 1 || B == 1) c = 1;
if (top->Ry <= top->By) {
if (R == 1) top->Ry--;
if (B == 1) top->By--;
}
else if (top->By < top->Ry) {
if (B == 1) top->By--;
if (R == 1) top->Ry--;
}
if (Board[top->By][top->Bx] == 'O')
return;
if (Board[top->Ry][top->Rx] == 'O') {
if (top->count < result) result = top->count;
return;
}
}
if (c == 1) {
top->flag = 'u';
check_the_way(Board, top);
}
else if (c == 0) {
top->flag = 'c';
check_the_way(Board, top);
}
}
void down(char** Board, Node* Ball) {
int R = 1, B = 1;
int c = 0;
Node* top = create(Ball);
while (R == 1 || B == 1) {
if (Board[top->Ry + 1][top->Rx] == '#' || (top->Ry + 1 == top->By && top->Rx == top->Bx))
R = 0;
if (Board[top->By + 1][top->Bx] == '#' || (top->By + 1 == top->Ry && top->Bx == top->Rx))
B = 0;
if (R == 1 || B == 1) c = 1;
if (top->Ry >= top->By) {
if (R == 1) top->Ry++;
if (B == 1) top->By++;
}
else if (top->By > top->Ry) {
if (B == 1) top->By++;
if (R == 1) top->Ry++;
}
if (Board[top->By][top->Bx] == 'O')
return;
if (Board[top->Ry][top->Rx] == 'O') {
if (top->count < result) result = top->count;
return;
}
}
if (c == 1) {
top->flag = 'd';
check_the_way(Board, top);
}
else if (c == 0) {
top->flag = 'c';
check_the_way(Board, top);
}
}
void left(char** Board, Node* Ball) {
int R = 1, B = 1;
int c = 0;
Node* top = create(Ball);
while (R == 1 || B == 1) {
if (Board[top->Ry][top->Rx - 1] == '#' || (top->Rx - 1 == top->Bx && top->Ry == top->By))
R = 0;
if (Board[top->By][top->Bx - 1] == '#' || (top->Bx - 1 == top->Rx && top->By == top->Ry))
B = 0;
if (R == 1 || B == 1) c = 1;
if (top->Rx <= top->Bx) {
if (R == 1) top->Rx--;
if (B == 1) top->Bx--;
}
else if (top->Bx < top->Rx) {
if (B == 1) top->Bx--;
if (R == 1) top->Rx--;
}
if (Board[top->By][top->Bx] == 'O')
return;
if (Board[top->Ry][top->Rx] == 'O') {
if (top->count < result) result = top->count;
return;
}
}
if (c == 1) {
top->flag = 'l';
check_the_way(Board, top);
}
else if (c == 0) {
top->flag = 'c';
check_the_way(Board, top);
}
}
void right(char** Board, Node* Ball) {
int R = 1, B = 1;
int c = 0;
Node* top = create(Ball);
while (R == 1 || B == 1) {
if (Board[top->Ry][top->Rx + 1] == '#' || (top->Rx + 1 == top->Bx && top->Ry == top->By))
R = 0;
if (Board[top->By][top->Bx + 1] == '#' || (top->Bx + 1 == top->Rx && top->By == top->Ry))
B = 0;
if (R == 1 || B == 1) c = 1;
if (top->Rx >= top->Bx) {
if (R == 1) top->Rx++;
if (B == 1) top->Bx++;
}
else if (top->Bx > top->Rx) {
if (B == 1) top->Bx++;
if (R == 1) top->Rx++;
}
if (Board[top->By][top->Bx] == 'O')
return;
if (Board[top->Ry][top->Rx] == 'O') {
if (top->count < result) result = top->count;
return;
}
}
if (c == 1) {
top->flag = 'r';
check_the_way(Board, top);
}
else if (c == 0) {
top->flag = 'c';
check_the_way(Board, top);
}
}
void check_the_way(char** Board, Node* top) {
if (top->flag == 'c') {
delete(top);
return;
}
if (Board[top->Ry - 1][top->Rx] != '#' && top->flag != 'd')
up(Board, top);
else if (Board[top->Ry + 1][top->Rx] != '#' && top->flag != 'u')
down(Board, top);
else if (Board[top->Ry][top->Rx - 1] != '#' && top->flag != 'r')
left(Board, top);
else if (Board[top->Ry][top->Rx + 1] != '#' && top->flag != 'l')
right(Board, top);
}
int main() {
int N, M;
scanf("%d %d", &N, &M);
getchar();
Node* Ball;
Ball = (Node*)malloc(sizeof(Node));
char** Board;
Board = (char**)calloc(N, sizeof(char*));
for (int i = 0; i < N; i++)
Board[i] = (char*)calloc(M, sizeof(char));
for (int i = 0; i < N; i++) {
for (int j = 0; j < M; j++)
scanf("%c", &Board[i][j]);
getchar();
}
init(Board, N, M, Ball);
check_the_way(Board, Ball);
printf("%d", result);
return 0;
}
'''GPT가 refactoring한 코드
#define MAX_N 10
#define MAX_M 10
// Define structure to hold game board state
typedef struct {
char cells[MAX_N][MAX_M];
int red_row, red_col, blue_row, blue_col;
} board_t;
// Define recursive function to solve game
int solve(board_t board, int last_move) {
// Check if current state is a winning or losing position
int red_in_goal = 0, blue_in_goal = 0;
for (int i = 0; i < MAX_N; i++) {
for (int j = 0; j < MAX_M; j++) {
if (board.cells[i][j] == 'R') {
if (i == board.red_row && j == board.red_col) {
red_in_goal = 1;
}
} else if (board.cells[i][j] == 'B') {
if (i == board.blue_row && j == board.blue_col) {
blue_in_goal = 1;
}
}
}
}
if (red_in_goal && !blue_in_goal) {
return 1; // Red ball in goal, game won
} else if (blue_in_goal || last_move == 10) {
return -1; // Blue ball in goal or too many moves, game lost
}
// Loop through possible directions
int directions[4][2] = {
{-1, 0}, {1, 0}, {0, -1}, {0, 1}
};
for (int i = 0; i < 4; i++) {
// Simulate moving balls in this direction
int red_new_row = board.red_row + directions[i][0];
int red_new_col = board.red_col + directions[i][1];
int blue_new_row = board.blue_row + directions[i][0];
int blue_new_col = board.blue_col + directions[i][1];
// Check if red ball can move in this direction
if (board.cells[red_new_row][red_new_col] == '.') {
// Move red ball
board.cells[board.red_row][board.red_col] = '.';
board.cells[red_new_row][red_new_col] = 'R';
board.red_row = red_new_row;
board.red_col = red_new_col;
// Check if blue ball can move in this direction
if (board.cells[blue_new_row][blue_new_col] == '.') {
// Move blue ball
board.cells[board.blue_row][board.blue_col] = '.';
board.cells[blue_new_row][blue_new_col] = 'B';
board.blue_row = blue_new_row;
board.blue_col = blue_new_col;
// Check if resulting state is valid
int valid = 1;
if (red_new_row == blue_new_row && red_new_col == blue_new_col) {
if (i == 0) { // Up
valid = board.red_row < board.blue_row;
} else if (i == 1) { // Down
valid = board.red_row > board.blue_row;
} else if (i == 2) { // Left
valid = board.red_col < board.blue_col;
} else if (i == 3) { // Right
valid = board.red_col > board.blue_col;
}
if (!valid) {
// Move blue ball back
board.cells[board.blue_row][board.blue_col] = '.';
board.cells[blue_new_row - directions[i][0]][blue_new_col - directions[i][1]] = 'B';
board.blue_row -= directions[i][0];
board.blue_col -= directions[i][1];
}
}
// If resulting state is valid, recursively call function
if (valid) {
int result = solve(board, i);
if (result == 1) {
return 1;
}
}
}
// If blue ball cannot move, move red ball back
board.cells[board.red_row][board.red_col] = '.';
board.cells[red_new_row - directions[i][0]][red_new_col - directions[i][1]] = 'R';
board.red_row -= directions[i][0];
board.red_col -= directions[i][1];
}
}
// If none of the recursive calls returned a winning position, return -1
return -1;
}
int main() {
// Read input and initialize game board state
int n, m;
scanf("%d %d", &n, &m);
board_t board;
for (int i = 0; i < n; i++) {
scanf("%s", board.cells[i]);
for (int j = 0; j < m; j++) {
if (board.cells[i][j] == 'R') {
board.red_row = i;
board.red_col = j;
}
else if (board.cells[i][j] == 'B') {
board.blue_row = i;
board.blue_col = j;
}
}
}
printf(solve(board, 0));
return 0;
}
'''
Python
import sys
input = sys.stdin.readline
# 구슬 움직임 체크 함수
def move(x, y, dx, dy):
cnt = 0
# 못 움직이기 전까지 +1하면서 움직여준다
while board[y+dy][x+dx] != '#' and board[y][x] != 'O':
x += dx
y += dy
cnt += 1
return x, y, cnt
def bfs(rx, ry, bx, by):
# 각각 움직일 수 있는 좌표를 체크해둔다.
dx, dy = (-1, 0, 1, 0), (0, -1, 0, 1)
# 큐에 2 구슬의 좌표값과 카운트 값 같이 넣어둠
queue = []
queue.append((rx,ry,bx,by,0))
visited[rx][ry][bx][by] = True
while queue:
now = queue.pop(0)
# 10번 이상 움직이면 체크할 필요 없다.
if now[4] >= 10:
continue
# 2 구슬은 같은 방향으로 움직여야하니 4가지 방향에 대해서만 각각 체크해줌
for xd, yd in zip(dx,dy):
rx, ry, bx, by, cnt = now[0], now[1], now[2], now[3], now[4]
# 전부 움직였을 때 최종 위치와 각 구슬이 움직인 횟수 체크
rx, ry, rcnt = move(rx, ry, xd, yd)
bx, by, bcnt = move(bx, by, xd, yd)
cnt += 1
# 파란게 들어갔으면 안되니까 continue
if board[by][bx] == 'O':
visited[rx][ry][bx][by] = True
continue
# 빨간게 들어갔으면 그대로 움직인 횟수 반환
if board[ry][rx] == 'O':
visited[rx][ry][bx][by] = True
return cnt
# 만약 두 구슬이 같은 위치에 있을 때,
# 둘 중 더 많이 움직인걸 한칸 전 좌표로 바꿔준다.
if rx == bx and ry == by:
if rcnt > bcnt:
rx -= xd
ry -= yd
else:
bx -= xd
by -= yd
# 현재 두 구슬의 위치가 한번도 나온 적 없는 모양이라면 방문체크하고 큐에 넣는다.
if visited[rx][ry][bx][by] == False:
visited[rx][ry][bx][by] = True
queue.append((rx, ry, bx, by, cnt))
# 아무리 해도 통과 못하면 -1
return -1
if __name__ == '__main__':
n, m = map(int, input().split())
board = [list(input().strip()) for _ in range(n)]
# 두 구슬의 위치를 한번에 체크한다.
visited = [[[[False] * n for _ in range(m)] for _ in range(n)] for _ in range(m)]
# 빨간 구슬, 파란 구슬 위치 찾아서 따로 저장하고 . 으로 바꿔준다.
for y in range(n):
for x in range(m):
if board[y][x] == 'R':
rx, ry = x, y
board[y][x] = '.'
elif board[y][x] == 'B':
bx, by = x, y
board[y][x] = '.'
# bfs로 탐색하고 나온 값 출력
print(bfs(rx, ry, bx, by))
문제
스타트링크에서 판매하는 어린이용 장난감 중에서 가장 인기가 많은 제품은 구슬 탈출이다. 구슬 탈출은 직사각형 보드에 빨간 구슬과 파란 구슬을 하나씩 넣은 다음, 빨간 구슬을 구멍을 통해 빼내는 게임이다.
보드의 세로 크기는 N, 가로 크기는 M이고, 편의상 1×1크기의 칸으로 나누어져 있다. 가장 바깥 행과 열은 모두 막혀져 있고, 보드에는 구멍이 하나 있다. 빨간 구슬과 파란 구슬의 크기는 보드에서 1×1크기의 칸을 가득 채우는 사이즈이고, 각각 하나씩 들어가 있다. 게임의 목표는 빨간 구슬을 구멍을 통해서 빼내는 것이다. 이때, 파란 구슬이 구멍에 들어가면 안 된다.
이때, 구슬을 손으로 건드릴 수는 없고, 중력을 이용해서 이리 저리 굴려야 한다. 왼쪽으로 기울이기, 오른쪽으로 기울이기, 위쪽으로 기울이기, 아래쪽으로 기울이기와 같은 네 가지 동작이 가능하다.
각각의 동작에서 공은 동시에 움직인다. 빨간 구슬이 구멍에 빠지면 성공이지만, 파란 구슬이 구멍에 빠지면 실패이다. 빨간 구슬과 파란 구슬이 동시에 구멍에 빠져도 실패이다. 빨간 구슬과 파란 구슬은 동시에 같은 칸에 있을 수 없다. 또, 빨간 구슬과 파란 구슬의 크기는 한 칸을 모두 차지한다. 기울이는 동작을 그만하는 것은 더 이상 구슬이 움직이지 않을 때 까지이다.
보드의 상태가 주어졌을 때, 최소 몇 번 만에 빨간 구슬을 구멍을 통해 빼낼 수 있는지 구하는 프로그램을 작성하시오.
입력
첫 번째 줄에는 보드의 세로, 가로 크기를 의미하는 두 정수 N, M (3 ≤ N, M ≤ 10)이 주어진다. 다음 N개의 줄에 보드의 모양을 나타내는 길이 M의 문자열이 주어진다. 이 문자열은 '.', '#', 'O', 'R', 'B' 로 이루어져 있다. '.'은 빈 칸을 의미하고, '#'은 공이 이동할 수 없는 장애물 또는 벽을 의미하며, 'O'는 구멍의 위치를 의미한다. 'R'은 빨간 구슬의 위치, 'B'는 파란 구슬의 위치이다.
입력되는 모든 보드의 가장자리에는 모두 '#'이 있다. 구멍의 개수는 한 개 이며, 빨간 구슬과 파란 구슬은 항상 1개가 주어진다.
출력
최소 몇 번 만에 빨간 구슬을 구멍을 통해 빼낼 수 있는지 출력한다. 만약, 10번 이하로 움직여서 빨간 구슬을 구멍을 통해 빼낼 수 없으면 -1을 출력한다.
제한
예제 입력 1
복사
5 5
#####
#..B#
#.#.#
#RO.#
#####
예제 출력 1
복사
1
예제 입력 2
복사
7 7
#######
#...RB#
#.#####
#.....#
#####.#
#O....#
#######
예제 출력 2
복사
5
예제 입력 3
복사
7 7
#######
#..R#B#
#.#####
#.....#
#####.#
#O....#
#######
예제 출력 3
복사
5
예제 입력 4
복사
10 10
##########
#R#...##B#
#...#.##.#
#####.##.#
#......#.#
#.######.#
#.#....#.#
#.#.#.#..#
#...#.O#.#
##########
예제 출력 4
복사
-1
예제 입력 5
복사
3 7
#######
#R.O.B#
#######
예제 출력 5
복사
1
예제 입력 6
복사
10 10
##########
#R#...##B#
#...#.##.#
#####.##.#
#......#.#
#.######.#
#.#....#.#
#.#.##...#
#O..#....#
##########
예제 출력 6
복사
7
예제 입력 7
복사
3 10
##########
#.O....RB#
##########
예제 출력 7
복사
-1
힌트
-
트럭
출처 : 트럭
Solution
Python
import sys
input = sys.stdin.readline
from collections import deque
if __name__ == '__main__':
# n = 트럭 수 / w = 다리 길이 / L = 다리 하중
n, w, L = map(int, input().split())
truck = deque(map(int, input().split()))
# 다리 위 각 (트럭의 무게, 현재 위치)
bridge = deque()
# 첫번째 트럭은 우선 다리 위에 올려준다.
t = truck.popleft()
bridge.append([t, 0])
# 시간은 1부터 시작, 현재 다리 위의 무게
answer, now = 1, t
# 남은 트럭이 있거나, 다리 위에 트럭이 있다면,
while truck or bridge:
# 일단 시간을 +1 해주고, 현상 확인
answer += 1
for i in range(len(bridge)): bridge[i][1] += 1
# 트럭이 다리 밖으로 나간다면, bridge에서 제거
if bridge[0][1]==w:
t, p = bridge.popleft()
now -= t
# 다음 트럭이 다리 위에 올라갈 수 있는 상태라면
if truck and ((now+truck[0]) <= L):
# 다리 위에 트럭 올려준다.
t = truck.popleft()
bridge.append([t, 0])
now += t
# 최종적으로 걸린 시간 출력
print(answer)
'''
if __name__ == '__main__':
# n = 트럭 수 / w = 다리 길이 / L = 다리 하중
n, w, L = map(int, input().split())
a = list(map(int, input().split()))
answer = 0
# 현재 다리 위의 무게, 트럭 교체가 일어난 횟수
now, cnt = 0, 0
# 다리 위 각 (트럭의 무게, 현재 위치)
Q = deque()
for i in a:
# 현재 트럭이 다리 위에 올라갈 수 있는 상태라면
if (now+i) <= L:
# 다리 위 트럭의 위치를 +1 해주고, 현재 트럭을 올려준다.
for j in range(len(Q)): Q[j][1] += 1
Q.append([i,0])
now += i
# 트럭 올라갈 때마다 시간+1
answer += 1
# 현재 트럭이 못 올라가는 상태라면
else:
# i 트럭이 올라갈 수 있을 때까지 빼준다.
while ((now+i) > L):
t, p = Q.popleft()
now -= t
# 트럭이 빠져나오기 까지 걸린 시간=w-p
k = (w-p)
answer += k
# 남은 트럭들 위치도 k만큼 이동시켜준다.
for j in range(len(Q)): Q[j][1] += k
# 현재 트럭을 다리에 올려주고, 현재 하중을 더해준다.
Q.append([i,0])
now += i
# 마지막 트럭이 나오는데 걸릴 시간(w)를 더해준다.
print(answer+w)
'''
문제
강을 가로지르는 하나의 차선으로 된 다리가 하나 있다. 이 다리를 n 개의 트럭이 건너가려고 한다. 트럭의 순서는 바꿀 수 없으며, 트럭의 무게는 서로 같지 않을 수 있다. 다리 위에는 단지 w 대의 트럭만 동시에 올라갈 수 있다. 다리의 길이는 w 단위길이(unit distance)이며, 각 트럭들은 하나의 단위시간(unit time)에 하나의 단위길이만큼만 이동할 수 있다고 가정한다. 동시에 다리 위에 올라가 있는 트럭들의 무게의 합은 다리의 최대하중인 L보다 작거나 같아야 한다. 참고로, 다리 위에 완전히 올라가지 못한 트럭의 무게는 다리 위의 트럭들의 무게의 합을 계산할 때 포함하지 않는다고 가정한다.
예를 들어, 다리의 길이 w는 2, 다리의 최대하중 L은 10, 다리를 건너려는 트럭이 트럭의 무게가 [7, 4, 5, 6]인 순서대로 다리를 오른쪽에서 왼쪽으로 건넌다고 하자. 이 경우 모든 트럭이 다리를 건너는 최단시간은 아래의 그림에서 보는 것과 같이 8 이다.
Figure 1. 본문의 예에 대해 트럭들이 다리를 건너는 과정.
다리의 길이와 다리의 최대하중, 그리고 다리를 건너려는 트럭들의 무게가 순서대로 주어졌을 때, 모든 트럭이 다리를 건너는 최단시간을 구하는 프로그램을 작성하라.
입력
입력 데이터는 표준입력을 사용한다. 입력은 두 줄로 이루어진다. 입력의 첫 번째 줄에는 세 개의 정수 n (1 ≤ n ≤ 1,000) , w (1 ≤ w ≤ 100) and L (10 ≤ L ≤ 1,000)이 주어지는데, n은 다리를 건너는 트럭의 수, w는 다리의 길이, 그리고 L은 다리의 최대하중을 나타낸다. 입력의 두 번째 줄에는 n개의 정수 a1, a2, ⋯ , an (1 ≤ ai ≤ 10)가 주어지는데, ai는 i번째 트럭의 무게를 나타낸다.
출력
출력은 표준출력을 사용한다. 모든 트럭들이 다리를 건너는 최단시간을 출력하라.
제한
예제 입력 1
복사
4 2 10
7 4 5 6
예제 출력 1
복사
8
예제 입력 2
복사
1 100 100
10
예제 출력 2
복사
101
예제 입력 3
복사
10 100 100
10 10 10 10 10 10 10 10 10 10
예제 출력 3
복사
110
힌트
W3sicHJvYmxlbV9pZCI6IjEzMzM1IiwicHJvYmxlbV9sYW5nIjoiMCIsInRpdGxlIjoiXHVkMmI4XHViN2VkIiwiZGVzY3JpcHRpb24iOiI8cD5cdWFjMTVcdWM3NDQgXHVhYzAwXHViODVjXHVjOWMwXHViOTc0XHViMjk0IFx1ZDU1OFx1YjA5OFx1Yzc1OCBcdWNjMjhcdWMxMjBcdWM3M2NcdWI4NWMgXHViNDFjIFx1YjJlNFx1YjlhY1x1YWMwMCBcdWQ1NThcdWIwOTggXHVjNzg4XHViMmU0LiBcdWM3NzQgXHViMmU0XHViOWFjXHViOTdjIG4gXHVhYzFjXHVjNzU4IFx1ZDJiOFx1YjdlZFx1Yzc3NCBcdWFjNzRcdWIxMDhcdWFjMDBcdWI4MjRcdWFjZTAgXHVkNTVjXHViMmU0LiBcdWQyYjhcdWI3ZWRcdWM3NTggXHVjMjFjXHVjMTFjXHViMjk0IFx1YmMxNFx1YWZjMCBcdWMyMTggXHVjNWM2XHVjNzNjXHViYTcwLCBcdWQyYjhcdWI3ZWRcdWM3NTggXHViYjM0XHVhYzhjXHViMjk0IFx1YzExY1x1Yjg1YyBcdWFjMTlcdWM5YzAgXHVjNTRhXHVjNzQ0IFx1YzIxOCBcdWM3ODhcdWIyZTQuIFx1YjJlNFx1YjlhYyBcdWM3MDRcdWM1ZDBcdWIyOTQgXHViMmU4XHVjOWMwIHcgXHViMzAwXHVjNzU4IFx1ZDJiOFx1YjdlZFx1YjljYyBcdWIzZDlcdWMyZGNcdWM1ZDAgXHVjNjJjXHViNzdjXHVhYzA4IFx1YzIxOCBcdWM3ODhcdWIyZTQuIFx1YjJlNFx1YjlhY1x1Yzc1OCBcdWFlMzhcdWM3NzRcdWIyOTQgdyBcdWIyZThcdWM3MDRcdWFlMzhcdWM3NzQodW5pdCBkaXN0YW5jZSlcdWM3NzRcdWJhNzAsIFx1YWMwMSBcdWQyYjhcdWI3ZWRcdWI0ZTRcdWM3NDAgXHVkNTU4XHViMDk4XHVjNzU4IFx1YjJlOFx1YzcwNFx1YzJkY1x1YWMwNCh1bml0IHRpbWUpXHVjNWQwIFx1ZDU1OFx1YjA5OFx1Yzc1OCBcdWIyZThcdWM3MDRcdWFlMzhcdWM3NzRcdWI5Y2NcdWQwN2NcdWI5Y2MgXHVjNzc0XHViM2Q5XHVkNTYwIFx1YzIxOCBcdWM3ODhcdWIyZTRcdWFjZTAgXHVhYzAwXHVjODE1XHVkNTVjXHViMmU0LiBcdWIzZDlcdWMyZGNcdWM1ZDAgXHViMmU0XHViOWFjIFx1YzcwNFx1YzVkMCBcdWM2MmNcdWI3N2NcdWFjMDAgXHVjNzg4XHViMjk0IFx1ZDJiOFx1YjdlZFx1YjRlNFx1Yzc1OCBcdWJiMzRcdWFjOGNcdWM3NTggXHVkNTY5XHVjNzQwIFx1YjJlNFx1YjlhY1x1Yzc1OCBcdWNkNWNcdWIzMDBcdWQ1NThcdWM5MTFcdWM3NzggTFx1YmNmNFx1YjJlNCBcdWM3OTFcdWFjNzBcdWIwOTggXHVhYzE5XHVjNTQ0XHVjNTdjIFx1ZDU1Y1x1YjJlNC4gXHVjYzM4XHVhY2UwXHViODVjLCBcdWIyZTRcdWI5YWMgXHVjNzA0XHVjNWQwIFx1YzY0NFx1YzgwNFx1ZDc4OCBcdWM2MmNcdWI3N2NcdWFjMDBcdWM5YzAgXHViYWJiXHVkNTVjIFx1ZDJiOFx1YjdlZFx1Yzc1OCBcdWJiMzRcdWFjOGNcdWIyOTQgXHViMmU0XHViOWFjIFx1YzcwNFx1Yzc1OCBcdWQyYjhcdWI3ZWRcdWI0ZTRcdWM3NTggXHViYjM0XHVhYzhjXHVjNzU4IFx1ZDU2OVx1Yzc0NCBcdWFjYzRcdWMwYjBcdWQ1NjAgXHViNTRjIFx1ZDNlY1x1ZDU2OFx1ZDU1OFx1YzljMCBcdWM1NGFcdWIyOTRcdWIyZTRcdWFjZTAgXHVhYzAwXHVjODE1XHVkNTVjXHViMmU0LjxcL3A+XHJcblxyXG48cD5cdWM2MDhcdWI5N2MgXHViNGU0XHVjNWI0LCBcdWIyZTRcdWI5YWNcdWM3NTggXHVhZTM4XHVjNzc0IHdcdWIyOTQgMiwgXHViMmU0XHViOWFjXHVjNzU4IFx1Y2Q1Y1x1YjMwMFx1ZDU1OFx1YzkxMSBMXHVjNzQwIDEwLCBcdWIyZTRcdWI5YWNcdWI5N2MgXHVhYzc0XHViMTA4XHViODI0XHViMjk0IFx1ZDJiOFx1YjdlZFx1Yzc3NCBcdWQyYjhcdWI3ZWRcdWM3NTggXHViYjM0XHVhYzhjXHVhYzAwIFs3LCA0LCA1LCA2XVx1Yzc3OCBcdWMyMWNcdWMxMWNcdWIzMDBcdWI4NWMgXHViMmU0XHViOWFjXHViOTdjIFx1YzYyNFx1Yjk3OFx1Y2FiZFx1YzVkMFx1YzExYyBcdWM2N2NcdWNhYmRcdWM3M2NcdWI4NWMgXHVhYzc0XHViMTBjXHViMmU0XHVhY2UwIFx1ZDU1OFx1Yzc5MC4gXHVjNzc0IFx1YWNiZFx1YzZiMCBcdWJhYThcdWI0ZTAgXHVkMmI4XHViN2VkXHVjNzc0IFx1YjJlNFx1YjlhY1x1Yjk3YyBcdWFjNzRcdWIxMDhcdWIyOTQgXHVjZDVjXHViMmU4XHVjMmRjXHVhYzA0XHVjNzQwIFx1YzU0NFx1Yjc5OFx1Yzc1OCBcdWFkZjhcdWI5YmNcdWM1ZDBcdWMxMWMgXHViY2Y0XHViMjk0IFx1YWM4M1x1YWNmYyBcdWFjMTlcdWM3NzQgOCBcdWM3NzRcdWIyZTQuPFwvcD5cclxuXHJcbjxwIHN0eWxlPVwidGV4dC1hbGlnbjogY2VudGVyO1wiPjxpbWcgYWx0PVwiXCIgc3JjPVwiaHR0cHM6XC9cL29ubGluZWp1ZGdlaW1hZ2VzLnMzLWFwLW5vcnRoZWFzdC0xLmFtYXpvbmF3cy5jb21cL3Byb2JsZW1cLzEzMzM1XC8xLnBuZ1wiIHN0eWxlPVwiaGVpZ2h0OjIxNHB4OyB3aWR0aDo2NjRweFwiIFwvPjxcL3A+XHJcblxyXG48cCBzdHlsZT1cInRleHQtYWxpZ246IGNlbnRlcjtcIj5GaWd1cmUgMS4gXHViY2Y4XHViYjM4XHVjNzU4IFx1YzYwOFx1YzVkMCBcdWIzMDBcdWQ1NzQgXHVkMmI4XHViN2VkXHViNGU0XHVjNzc0IFx1YjJlNFx1YjlhY1x1Yjk3YyBcdWFjNzRcdWIxMDhcdWIyOTQgXHVhY2ZjXHVjODE1LjxcL3A+XHJcblxyXG48cD5cdWIyZTRcdWI5YWNcdWM3NTggXHVhZTM4XHVjNzc0XHVjNjQwIFx1YjJlNFx1YjlhY1x1Yzc1OCBcdWNkNWNcdWIzMDBcdWQ1NThcdWM5MTEsIFx1YWRmOFx1YjlhY1x1YWNlMCBcdWIyZTRcdWI5YWNcdWI5N2MgXHVhYzc0XHViMTA4XHViODI0XHViMjk0IFx1ZDJiOFx1YjdlZFx1YjRlNFx1Yzc1OCBcdWJiMzRcdWFjOGNcdWFjMDAgXHVjMjFjXHVjMTFjXHViMzAwXHViODVjIFx1YzhmY1x1YzViNFx1Yzg0Y1x1Yzc0NCBcdWI1NGMsIFx1YmFhOFx1YjRlMCBcdWQyYjhcdWI3ZWRcdWM3NzQgXHViMmU0XHViOWFjXHViOTdjIFx1YWM3NFx1YjEwOFx1YjI5NCBcdWNkNWNcdWIyZThcdWMyZGNcdWFjMDRcdWM3NDQgXHVhZDZjXHVkNTU4XHViMjk0IFx1ZDUwNFx1Yjg1Y1x1YWRmOFx1YjdhOFx1Yzc0NCBcdWM3OTFcdWMxMzFcdWQ1NThcdWI3N2MuPFwvcD5cclxuIiwiaW5wdXQiOiI8cD5cdWM3ODVcdWI4MjUgXHViMzcwXHVjNzc0XHVkMTMwXHViMjk0IFx1ZDQ1Y1x1YzkwMFx1Yzc4NVx1YjgyNVx1Yzc0NCBcdWMwYWNcdWM2YTlcdWQ1NWNcdWIyZTQuIFx1Yzc4NVx1YjgyNVx1Yzc0MCBcdWI0NTAgXHVjOTA0XHViODVjIFx1Yzc3NFx1YjhlOFx1YzViNFx1YzljNFx1YjJlNC4gXHVjNzg1XHViODI1XHVjNzU4IFx1Y2NhYiBcdWJjODhcdWM5ZjggXHVjOTA0XHVjNWQwXHViMjk0IFx1YzEzOCBcdWFjMWNcdWM3NTggXHVjODE1XHVjMjE4IG4gKDEgJmxlOyBuICZsZTsgMSwwMDApICwgdyAoMSAmbGU7IHcgJmxlOyAxMDApIGFuZCBMICgxMCAmbGU7IEwgJmxlOyAxLDAwMClcdWM3NzQgXHVjOGZjXHVjNWI0XHVjOWMwXHViMjk0XHViMzcwLCBuXHVjNzQwIFx1YjJlNFx1YjlhY1x1Yjk3YyBcdWFjNzRcdWIxMDhcdWIyOTQgXHVkMmI4XHViN2VkXHVjNzU4IFx1YzIxOCwgd1x1YjI5NCBcdWIyZTRcdWI5YWNcdWM3NTggXHVhZTM4XHVjNzc0LCBcdWFkZjhcdWI5YWNcdWFjZTAgTFx1Yzc0MCBcdWIyZTRcdWI5YWNcdWM3NTggXHVjZDVjXHViMzAwXHVkNTU4XHVjOTExXHVjNzQ0IFx1YjA5OFx1ZDBjMFx1YjBiOFx1YjJlNC4gXHVjNzg1XHViODI1XHVjNzU4IFx1YjQ1MCBcdWJjODhcdWM5ZjggXHVjOTA0XHVjNWQwXHViMjk0IG5cdWFjMWNcdWM3NTggXHVjODE1XHVjMjE4IGE8c3ViPjE8XC9zdWI+LCBhPHN1Yj4yPFwvc3ViPiwgXHUyMmVmICwgYTxzdWI+bjxcL3N1Yj4gKDEgJmxlOyBhPHN1Yj5pPFwvc3ViPiAmbGU7IDEwKVx1YWMwMCBcdWM4ZmNcdWM1YjRcdWM5YzBcdWIyOTRcdWIzNzAsIGE8c3ViPmk8XC9zdWI+XHViMjk0IGlcdWJjODhcdWM5ZjggXHVkMmI4XHViN2VkXHVjNzU4IFx1YmIzNFx1YWM4Y1x1Yjk3YyBcdWIwOThcdWQwYzBcdWIwYjhcdWIyZTQuPFwvcD5cclxuIiwib3V0cHV0IjoiPHA+XHVjZDljXHViODI1XHVjNzQwIFx1ZDQ1Y1x1YzkwMFx1Y2Q5Y1x1YjgyNVx1Yzc0NCBcdWMwYWNcdWM2YTlcdWQ1NWNcdWIyZTQuIFx1YmFhOFx1YjRlMCBcdWQyYjhcdWI3ZWRcdWI0ZTRcdWM3NzQgXHViMmU0XHViOWFjXHViOTdjIFx1YWM3NFx1YjEwOFx1YjI5NCBcdWNkNWNcdWIyZThcdWMyZGNcdWFjMDRcdWM3NDQgXHVjZDljXHViODI1XHVkNTU4XHViNzdjLjxcL3A+XHJcbiIsImhpbnQiOiIiLCJvcmlnaW5hbCI6IjAiLCJodG1sX3RpdGxlIjoiMCIsInByb2JsZW1fbGFuZ190Y29kZSI6IktvcmVhbiJ9LHsicHJvYmxlbV9pZCI6IjEzMzM1IiwicHJvYmxlbV9sYW5nIjoiMSIsInRpdGxlIjoiVHJ1Y2tzIiwiZGVzY3JpcHRpb24iOiI8cD5UaGVyZSBhcmUgbiBjYXJnbyB0cnVja3MgaW4gYSBsaW5lIHRvIGNyb3NzIGEgb25lIGxhbmUgd2lkZSBicmlkZ2Ugb3ZlciBhIHJpdmVyLiBUaGUgb3JkZXIgb2YgdHJ1Y2tzIGNhbm5vdCBiZSBjaGFuZ2VkIGFuZCB0aGUgd2VpZ2h0IG9mIGVhY2ggdHJ1Y2sgbWF5IG5vdCBiZSB0aGUgc2FtZS4gT25seSB3IHRydWNrcyBjYW4gYmUgb24gdGhlIGJyaWRnZSBhdCB0aGUgc2FtZSB0aW1lLiBXZSBhc3N1bWUgdGhhdCB0aGUgbGVuZ3RoIG9mIHRoZSBicmlkZ2UgaXMgdyB1bml0IGRpc3RhbmNlIGFuZCBlYWNoIHRydWNrIG1vdmVzIGEgdW5pdCBkaXN0YW5jZSBpbiBhIHVuaXQgdGltZS4gVGhlIHN1bSBvZiB0aGUgd2VpZ2h0cyBvZiB0aGUgdHJ1Y2tzIG9uIHRoZSBicmlkZ2Ugc2hvdWxkIGJlIGxlc3MgdGhhbiBvciBlcXVhbCB0byBMIGR1ZSB0byB0aGUgbWF4aW11bSBzYWZlIGxvYWQgb2YgdGhlIGJyaWRnZS4gTm90ZSB0aGF0IHRoZSB3ZWlnaHRzIG9mIHRydWNrcyB0aGF0IGFyZW4mcnNxdW87dCBmdWxseSBwcmVzZW50IG9uIHRoZSBicmlkZ2UgYXJlIG5vdCBjb25zaWRlcmVkIGluIHRoZSBsb2FkIGNhbGN1bGF0aW9uIG9mIHRoZSB0cnVja3Mgb24gdGhlIGJyaWRnZS48XC9wPlxyXG5cclxuPHA+Rm9yIGV4YW1wbGUsIGxldCB3IGJlIDIgYW5kIEwgYmUgMTAgYW5kIHRoZSBzZXF1ZW5jZSBvZiB0aGUgd2VpZ2h0cyBvZiB0aGUgdHJ1Y2tzIGJlIFs3LCA0LCA1LCA2XSBhbmQgdGhlIHRydWNrcyBhcmUgY3Jvc3NpbmcgZnJvbSByaWdodCB0byBsZWZ0LiBUaGVuLCB0aGUgZWFybGllc3QgdGltZSBmb3IgYWxsIHRoZSB0cnVja3MgdG8gY3Jvc3MgdGhlIGJyaWRnZSBpcyA4LCBhcyBpbGx1c3RyYXRlZCBpbiBGaWd1cmUgMS48XC9wPlxyXG5cclxuPHAgc3R5bGU9XCJ0ZXh0LWFsaWduOiBjZW50ZXI7XCI+PGltZyBhbHQ9XCJcIiBzcmM9XCJodHRwczpcL1wvb25saW5lanVkZ2VpbWFnZXMuczMtYXAtbm9ydGhlYXN0LTEuYW1hem9uYXdzLmNvbVwvcHJvYmxlbVwvMTMzMzVcLzEucG5nXCIgc3R5bGU9XCJoZWlnaHQ6MjE0cHg7IHRleHQtYWxpZ246Y2VudGVyOyB3aWR0aDo2NjRweFwiIFwvPjxcL3A+XHJcblxyXG48cCBzdHlsZT1cInRleHQtYWxpZ246IGNlbnRlcjtcIj5GaWd1cmUgMS4gVHJ1Y2tzIGNyb3NzaW5nIHRoZSBicmlkZ2UuPFwvcD5cclxuXHJcbjxwPllvdSBhcmUgZ2l2ZW4gdGhlIG1heGltdW0gYWZmb3JkYWJsZSBudW1iZXIgb2YgdGhlIHRydWNrcyBvbiB0aGUgYnJpZGdlIGFuZCB0aGUgbWF4aW11bSBzYWZlIGxvYWQgb2YgdGhlIGJyaWRnZSBhbmQgdGhlIHNlcXVlbmNlIG9mIHRoZSB3ZWlnaHRzIG9mIHRoZSB0cnVja3MuIFdyaXRlIGEgcHJvZ3JhbSBmb3IgZmluZGluZyB0aGUgZWFybGllc3QgdGltZSBmb3IgdGhlIHRydWNrcyB0byBjcm9zcyB0aGUgYnJpZGdlLjxcL3A+XHJcbiIsImlucHV0IjoiPHA+WW91ciBwcm9ncmFtIGlzIHRvIHJlYWQgZnJvbSBzdGFuZGFyZCBpbnB1dC4gVGhlIGlucHV0IGNvbnNpc3RzIG9mIHR3byBsaW5lcy4gVGhlIGZpcnN0IGxpbmUgY29udGFpbnMgdGhyZWUgaW50ZWdlcnMgbiAoMSAmbGU7IG4gJmxlOyAxLDAwMCksIHcgKDEgJmxlOyB3ICZsZTsgMTAwKSBhbmQgTCAoMTAgJmxlOyBMICZsZTsgMSwwMDApIHdoZXJlIG4gaXMgdGhlIG51bWJlciBvZiB0cnVja3MgdG8gY3Jvc3MgdGhlIGJyaWRnZSwgdyBpcyB0aGUgbWF4aW11bSBhZmZvcmRhYmxlIG51bWJlciBvZiB0cnVja3Mgb24gdGhlIGJyaWRnZSBhbmQgTCBpcyB0aGUgbWF4aW11bSBzYWZlIGxvYWQgb2YgdGhlIGJyaWRnZS4gVGhlIHNlY29uZCBsaW5lIGNvbnRhaW5zIG4gaW50ZWdlcnMgYTxzdWI+MTxcL3N1Yj4sIGE8c3ViPjI8XC9zdWI+LCBcdTIyZWYgLCBhPHN1Yj5uPFwvc3ViPiAoMSAmbGU7IGE8c3ViPmk8XC9zdWI+ICZsZTsgMTApLCB3aGVyZSBhPHN1Yj5pPFwvc3ViPiByZXByZXNlbnRzIHRoZSB3ZWlnaHQgb2YgaS10aCB0cnVjay48XC9wPlxyXG4iLCJvdXRwdXQiOiI8cD5Zb3VyIHByb2dyYW0gaXMgdG8gd3JpdGUgdG8gc3RhbmRhcmQgb3V0cHV0LiBQcmludCB0aGUgZWFybGllc3QgdGltZSB0byBjcm9zcyB0aGUgYnJpZGdlLiZuYnNwOzxcL3A+XHJcbiIsImhpbnQiOiIiLCJvcmlnaW5hbCI6IjEiLCJodG1sX3RpdGxlIjoiMCIsInByb2JsZW1fbGFuZ190Y29kZSI6IkVuZ2xpc2gifV0=
-
2048 (Easy)
출처 : 2048 (Easy)
Solution
Python
import sys
input = sys.stdin.readline
from collections import deque
import copy
def move_left(NOW):
board = copy.deepcopy(NOW)
N = len(board)
for y in range(N):
index = deque(list(range(N)))
value = 0
for x in range(N):
if board[y][x] > 0 and value == 0:
while index:
pos = index.popleft()
if board[y][pos] == 0 or pos == x: break
value, board[y][x] = board[y][x], 0
elif board[y][x] > 0 and value != 0:
if board[y][x] == value:
value += board[y][x]
board[y][x] = 0
board[y][pos], value = value, 0
elif board[y][x] != value:
board[y][pos] = value
while index:
pos = index.popleft()
if board[y][pos] == 0 or pos == x: break
value, board[y][x] = board[y][x], 0
if value != 0:
board[y][pos] = value
return board
def move_right(NOW):
board = copy.deepcopy(NOW)
N = len(board)
for y in range(N):
index = deque(list(range(N)))
value = 0
for x in range(N-1, -1, -1):
if board[y][x] > 0 and value == 0:
while index:
pos = index.pop()
if board[y][pos] == 0 or pos == x: break
value, board[y][x] = board[y][x], 0
elif board[y][x] > 0 and value != 0:
if board[y][x] == value:
value += board[y][x]
board[y][x] = 0
board[y][pos], value = value, 0
elif board[y][x] != value:
board[y][pos] = value
while index:
pos = index.pop()
if board[y][pos] == 0 or pos == x: break
value, board[y][x] = board[y][x], 0
if value != 0:
board[y][pos] = value
return board
def move_up(NOW):
board = copy.deepcopy(NOW)
N = len(board)
for x in range(N):
index = deque(list(range(N)))
value = 0
for y in range(N):
if board[y][x] > 0 and value == 0:
while index:
pos = index.popleft()
if board[pos][x] == 0 or pos == y: break
value, board[y][x] = board[y][x], 0
elif board[y][x] > 0 and value != 0:
if board[y][x] == value:
value += board[y][x]
board[y][x] = 0
board[pos][x], value = value, 0
elif board[y][x] != value:
board[pos][x] = value
while index:
pos = index.popleft()
if board[pos][x] == 0 or pos == y: break
value, board[y][x] = board[y][x], 0
if value != 0:
board[pos][x] = value
return board
def move_down(NOW):
board = copy.deepcopy(NOW)
N = len(board)
for x in range(N):
index = deque(list(range(N)))
value = 0
for y in range(N-1, -1, -1):
if board[y][x] > 0 and value == 0:
while index:
pos = index.pop()
if board[pos][x] == 0 or pos == y: break
value, board[y][x] = board[y][x], 0
elif board[y][x] > 0 and value != 0:
if board[y][x] == value:
value += board[y][x]
board[y][x] = 0
board[pos][x], value = value, 0
elif board[y][x] != value:
board[pos][x] = value
while index:
pos = index.pop()
if board[pos][x] == 0 or pos == y: break
value, board[y][x] = board[y][x], 0
if value != 0:
board[pos][x] = value
return board
def print_board(board):
MAX = max(map(max, board))
for y in range(len(board)):
for x in range(len(board)):
print(f'{board[y][x]:>{len(str(MAX))}d}', end=' ')
print()
print()
N = int(input())
origin_board = [list(map(int, input().split( ))) for _ in range(N)]
used_board = []
Q = deque()
Q.append((origin_board, 0))
answer = 0
while Q:
now_board, cnt = Q.popleft()
if not now_board in used_board and cnt < 5:
used_board.append(now_board)
board = move_left(now_board)
MAX = max(map(max, board))
answer = MAX if MAX > answer else answer
Q.append((board, cnt+1))
board = move_right(now_board)
MAX = max(map(max, board))
answer = MAX if MAX > answer else answer
Q.append((board, cnt+1))
board = move_up(now_board)
MAX = max(map(max, board))
answer = MAX if MAX > answer else answer
Q.append((board, cnt+1))
board = move_down(now_board)
MAX = max(map(max, board))
answer = MAX if MAX > answer else answer
Q.append((board, cnt+1))
print(answer)
문제
2048 게임은 4×4 크기의 보드에서 혼자 즐기는 재미있는 게임이다. 이 링크를 누르면 게임을 해볼 수 있다.
이 게임에서 한 번의 이동은 보드 위에 있는 전체 블록을 상하좌우 네 방향 중 하나로 이동시키는 것이다. 이때, 같은 값을 갖는 두 블록이 충돌하면 두 블록은 하나로 합쳐지게 된다. 한 번의 이동에서 이미 합쳐진 블록은 또 다른 블록과 다시 합쳐질 수 없다. (실제 게임에서는 이동을 한 번 할 때마다 블록이 추가되지만, 이 문제에서 블록이 추가되는 경우는 없다)
<그림 1>
<그림 2>
<그림 3>
<그림 1>의 경우에서 위로 블록을 이동시키면 <그림 2>의 상태가 된다. 여기서, 왼쪽으로 블록을 이동시키면 <그림 3>의 상태가 된다.
<그림 4>
<그림 5>
<그림 6>
<그림 7>
<그림 4>의 상태에서 블록을 오른쪽으로 이동시키면 <그림 5>가 되고, 여기서 다시 위로 블록을 이동시키면 <그림 6>이 된다. 여기서 오른쪽으로 블록을 이동시켜 <그림 7>을 만들 수 있다.
<그림 8>
<그림 9>
<그림 8>의 상태에서 왼쪽으로 블록을 옮기면 어떻게 될까? 2가 충돌하기 때문에, 4로 합쳐지게 되고 <그림 9>의 상태가 된다.
<그림 10>
<그림 11>
<그림 12>
<그림 13>
<그림 10>에서 위로 블록을 이동시키면 <그림 11>의 상태가 된다.
<그림 12>의 경우에 위로 블록을 이동시키면 <그림 13>의 상태가 되는데, 그 이유는 한 번의 이동에서 이미 합쳐진 블록은 또 합쳐질 수 없기 때문이다.
<그림 14>
<그림 15>
마지막으로, 똑같은 수가 세 개가 있는 경우에는 이동하려고 하는 쪽의 칸이 먼저 합쳐진다. 예를 들어, 위로 이동시키는 경우에는 위쪽에 있는 블록이 먼저 합쳐지게 된다. <그림 14>의 경우에 위로 이동하면 <그림 15>를 만든다.
이 문제에서 다루는 2048 게임은 보드의 크기가 N×N 이다. 보드의 크기와 보드판의 블록 상태가 주어졌을 때, 최대 5번 이동해서 만들 수 있는 가장 큰 블록의 값을 구하는 프로그램을 작성하시오.
입력
첫째 줄에 보드의 크기 N (1 ≤ N ≤ 20)이 주어진다. 둘째 줄부터 N개의 줄에는 게임판의 초기 상태가 주어진다. 0은 빈 칸을 나타내며, 이외의 값은 모두 블록을 나타낸다. 블록에 쓰여 있는 수는 2보다 크거나 같고, 1024보다 작거나 같은 2의 제곱꼴이다. 블록은 적어도 하나 주어진다.
출력
최대 5번 이동시켜서 얻을 수 있는 가장 큰 블록을 출력한다.
제한
예제 입력 1
복사
3
2 2 2
4 4 4
8 8 8
예제 출력 1
복사
16
힌트
-
-
플로이드
출처 : 플로이드
Solution
Python
import sys
input = sys.stdin.readline
import heapq
if __name__ == '__main__':
n = int(input())
m = int(input())
# 모든 값을 우선 무한대로 초기화
answer = [[float('inf')] * (n+1) for _ in range(n+1)]
# a에서 b로 가는 값을 c로 저장
for _ in range(m):
a,b,c = map(int, input().split())
answer[a][b] = min(answer[a][b], c)
# 자기자신에게 돌아오는 값은 0으로 초기화
for i in range(1, n+1): answer[i][i] = 0
# 시작지점 s에서 경유지 i를 거치고 f까지 가는 거리 계산
for i in range(1, n+1):
for s in range(1, n+1):
for f in range(1, n+1):
answer[s][f] = min(answer[s][f], answer[s][i]+answer[i][f])
# 출력
for ans in answer[1:]:
for a in ans[1:]:
if a==float('inf'): print(0, end=' ')
else: print(a, end=' ')
print()
문제
n(2 ≤ n ≤ 100)개의 도시가 있다. 그리고 한 도시에서 출발하여 다른 도시에 도착하는 m(1 ≤ m ≤ 100,000)개의 버스가 있다. 각 버스는 한 번 사용할 때 필요한 비용이 있다.
모든 도시의 쌍 (A, B)에 대해서 도시 A에서 B로 가는데 필요한 비용의 최솟값을 구하는 프로그램을 작성하시오.
입력
첫째 줄에 도시의 개수 n이 주어지고 둘째 줄에는 버스의 개수 m이 주어진다. 그리고 셋째 줄부터 m+2줄까지 다음과 같은 버스의 정보가 주어진다. 먼저 처음에는 그 버스의 출발 도시의 번호가 주어진다. 버스의 정보는 버스의 시작 도시 a, 도착 도시 b, 한 번 타는데 필요한 비용 c로 이루어져 있다. 시작 도시와 도착 도시가 같은 경우는 없다. 비용은 100,000보다 작거나 같은 자연수이다.
시작 도시와 도착 도시를 연결하는 노선은 하나가 아닐 수 있다.
출력
n개의 줄을 출력해야 한다. i번째 줄에 출력하는 j번째 숫자는 도시 i에서 j로 가는데 필요한 최소 비용이다. 만약, i에서 j로 갈 수 없는 경우에는 그 자리에 0을 출력한다.
제한
예제 입력 1
복사
5
14
1 2 2
1 3 3
1 4 1
1 5 10
2 4 2
3 4 1
3 5 1
4 5 3
3 5 10
3 1 8
1 4 2
5 1 7
3 4 2
5 2 4
예제 출력 1
복사
0 2 3 1 4
12 0 15 2 5
8 5 0 1 1
10 7 13 0 3
7 4 10 6 0
힌트
-
동전 0
출처 : 동전 0
Solution
Python
import sys
input = sys.stdin.readline
if __name__ == '__main__':
N, K = map(int, input().split())
A = [int(input()) for _ in range(N)]
answer = 0
# 큰 동전부터 확인
for i in range(N-1, -1, -1):
if K >= A[i]:
answer += (K//A[i])
K %= A[i]
if K==0: break
print(answer)
문제
준규가 가지고 있는 동전은 총 N종류이고, 각각의 동전을 매우 많이 가지고 있다.
동전을 적절히 사용해서 그 가치의 합을 K로 만들려고 한다. 이때 필요한 동전 개수의 최솟값을 구하는 프로그램을 작성하시오.
입력
첫째 줄에 N과 K가 주어진다. (1 ≤ N ≤ 10, 1 ≤ K ≤ 100,000,000)
둘째 줄부터 N개의 줄에 동전의 가치 Ai가 오름차순으로 주어진다. (1 ≤ Ai ≤ 1,000,000, A1 = 1, i ≥ 2인 경우에 Ai는 Ai-1의 배수)
출력
첫째 줄에 K원을 만드는데 필요한 동전 개수의 최솟값을 출력한다.
제한
예제 입력 1
복사
10 4200
1
5
10
50
100
500
1000
5000
10000
50000
예제 출력 1
복사
6
예제 입력 2
복사
10 4790
1
5
10
50
100
500
1000
5000
10000
50000
예제 출력 2
복사
12
힌트
-
강의실 배정
출처 : 강의실 배정
Solution
Python
import sys
input = sys.stdin.readline
# 해당 문제는 힙큐를 무조건 사용해야 한다.
import heapq
if __name__ == '__main__':
# N과 S, T 를 입력받는다.
N = int(input())
ST = [list(map(int, input().split())) for _ in range(N)]
# 우선 시작 시간 기준으로 정렬해준다.
ST.sort()
# 정답이 될 강의실 수
answer = 1
# 강의실 배정을 heap에 해주고,
heap = []
# 초기화를 위해 -1만 넣어준다.
heapq.heappush(heap, -1)
for st in ST:
# 현재 강의실 중 가장 일찍 끝나는 곳
m = heapq.heappop(heap)
# 해당 강의실이 현재 사용가능하면,
if st[0] >= m:
# 해당 강의실은 현재 강의의 끝나는 시간을 기록
heapq.heappush(heap, st[1])
# 현재 사용 불가라면
else:
# 가장 일찍 끝나는 강의실도 heap 에 다시 넣어주고
heapq.heappush(heap, m)
# 강의실 하나 더 추가해준다.
answer += 1
heapq.heappush(heap, st[1])
print(answer)
'''
min, index 이용해서 가장 일찍 끝나는 강의실 기준 체크
if __name__ == '__main__':
# N과 S, T 를 입력받는다.
N = int(input())
ST = [list(map(int, input().split())) for _ in range(N)]
# 강의실 넣어줄 answer 배열
answer = [-1]
# 모든 강의를 체크 시작 (Si 기준으로 정렬 돼있다 가정)
for st in ST:
# 현재 사용 강의실 중 가장 빨리 끝나는 곳 시간
m = min(answer)
# 해당 강의실이 현재 사용가능하면,
if st[0] >= m:
# 해당 강의실은 현재 강의의 끝나는 시간을 기록
answer[answer.index(m)] = st[1]
# 현재 사용 불가라면
else:
# 새로운 강의실을 할당
answer.append(st[1])
# 모든 강의 체크가 끝났다면, 사용한 강의실 수를 출력
print(len(answer))
'''
'''
# dict 이용해서 강의실 하나하나 체크하는 방법
if __name__ == '__main__':
# N과 S, T 를 입력받는다.
N = int(input())
ST = [list(map(int, input().split())) for _ in range(N)]
# 강의실 넣어줄 answer dict
answer = {0:-1}
# 모든 강의를 체크 시작 (Si 기준으로 정렬 돼있다 가정)
for st in ST:
# False 면 현재 빈 강의실이 없다!
chk = False
# answer의 강의실 중 비는 강의실이 있는지 체크
for i in range(len(answer)):
# 현재 강의 시작 시 비는 강의실 이 있다면,
if st[0] >= answer[i]:
# 해당 강의의 끝나는 시간을 강의실에 기록하고
answer[i] = st[1]
# 빈 강의실 있다고 체크해주자
chk = True
break
# 만약 빈 강의실이 없다면, 새로운 강의실 넣기
if not chk: answer[i+1] = st[1]
# 모든 강의 체크가 끝났다면, 사용한 강의실 수를 출력
print(len(answer))
'''
문제
수강신청의 마스터 김종혜 선생님에게 새로운 과제가 주어졌다.
김종혜 선생님한테는 Si에 시작해서 Ti에 끝나는 N개의 수업이 주어지는데, 최소의 강의실을 사용해서 모든 수업을 가능하게 해야 한다.
참고로, 수업이 끝난 직후에 다음 수업을 시작할 수 있다. (즉, Ti ≤ Sj 일 경우 i 수업과 j 수업은 같이 들을 수 있다.)
수강신청 대충한 게 찔리면, 선생님을 도와드리자!
입력
첫 번째 줄에 N이 주어진다. (1 ≤ N ≤ 200,000)
이후 N개의 줄에 Si, Ti가 주어진다. (0 ≤ Si < Ti ≤ 109)
출력
강의실의 개수를 출력하라.
제한
예제 입력 1
복사
3
1 3
2 4
3 5
예제 출력 1
복사
2
힌트
-
이중 우선순위 큐
출처 : 이중 우선순위 큐
Solution
Python
import sys
input = sys.stdin.readline
import heapq
if __name__ == '__main__':
T = int(input())
# 각 테스트 케이스마다 따로 입력 받기
for _ in range(T):
# 연산 갯수 먼저 입력받고
k = int(input())
# 최대값 우선순위 큐, 최소값 우선순위 큐를 각각 만든다.
maxQ, minQ = [], []
# 우선순위 큐 한쪽에서만 제거되면 다른 쪽에서는 모르는만큼,
# 현재 큐 내에 특정값이 몇개 있는지 체크해줄 딕셔너리를 선언
chkQ = dict()
# 연산 입력 시작
for _ in range(k):
# 입력받아주고나서, n은 정수형 변환해줌
op, n = input().strip().split()
n = int(n)
# I 연산이라면,
if op=='I':
# 최대값 우선순위 큐는 역순정렬되어야 하므로,
# -를 곱해서 튜플형태로 바꿔주고, 1인덱스에 원본값 보존
heapq.heappush(maxQ, (-n, n))
# 최소값 우선순위 큐에는 그냥 넣어주면 된다.
heapq.heappush(minQ, n)
# 딕셔너리에 해당 정수값 +1 해주는데, 없다면 새로 만들어준다.
try: chkQ[n] += 1
except: chkQ[n] = 1
else:
# D 연산일 때, 만약 heappop이 안되면 그냥 pass 해준다.
try:
# 최대값을 제거해야한다면,
if n==1:
# 튜플로 뽑히니깐 1인덱스 값이 구하는 값이다!
c = heapq.heappop(maxQ)[1]
# 만약 뽑은 값이 이미 없는 값이라면,
if not chkQ[c]:
# 있는 값이 될 때까지 뽑고,
while True:
c = heapq.heappop(maxQ)[1]
# 만약 큐 안에 존재하는 값이면, -1하고 반복문 탈출
if chkQ[c]:
chkQ[c] -= 1
break
# 이미 있는 값이면 그냥 -1 해주면 된다.
else: chkQ[c] -= 1
# 최소값 제거는 평범하게 제거하고 체크해주면 된다.
else:
c = heapq.heappop(minQ)
if not chkQ[c]:
while True:
c = heapq.heappop(minQ)
if chkQ[c]:
chkQ[c] -= 1
break
else: chkQ[c] -= 1
except: pass
# 모든 연산이 끝났는데, chkQ의 값(모든 정수값)이 전부 0이라 큐에 값이 없다면 EMPTY
if all(v==0 for v in chkQ.values()): print('EMPTY')
else:
# 아니면 M, m 에 큐 안의 최대 최소값을 넣어주고, 출력해준다.
while True:
M = heapq.heappop(maxQ)[1]
if chkQ[M]: break
while True:
m = heapq.heappop(minQ)
if chkQ[m]: break
print(M, m)
문제
이중 우선순위 큐(dual priority queue)는 전형적인 우선순위 큐처럼 데이터를 삽입, 삭제할 수 있는 자료 구조이다. 전형적인 큐와의 차이점은 데이터를 삭제할 때 연산(operation) 명령에 따라 우선순위가 가장 높은 데이터 또는 가장 낮은 데이터 중 하나를 삭제하는 점이다. 이중 우선순위 큐를 위해선 두 가지 연산이 사용되는데, 하나는 데이터를 삽입하는 연산이고 다른 하나는 데이터를 삭제하는 연산이다. 데이터를 삭제하는 연산은 또 두 가지로 구분되는데 하나는 우선순위가 가장 높은 것을 삭제하기 위한 것이고 다른 하나는 우선순위가 가장 낮은 것을 삭제하기 위한 것이다.
정수만 저장하는 이중 우선순위 큐 Q가 있다고 가정하자. Q에 저장된 각 정수의 값 자체를 우선순위라고 간주하자.
Q에 적용될 일련의 연산이 주어질 때 이를 처리한 후 최종적으로 Q에 저장된 데이터 중 최댓값과 최솟값을 출력하는 프로그램을 작성하라.
입력
입력 데이터는 표준입력을 사용한다. 입력은 T개의 테스트 데이터로 구성된다. 입력의 첫 번째 줄에는 입력 데이터의 수를 나타내는 정수 T가 주어진다. 각 테스트 데이터의 첫째 줄에는 Q에 적용할 연산의 개수를 나타내는 정수 k (k ≤ 1,000,000)가 주어진다. 이어지는 k 줄 각각엔 연산을 나타내는 문자(‘D’ 또는 ‘I’)와 정수 n이 주어진다. ‘I n’은 정수 n을 Q에 삽입하는 연산을 의미한다. 동일한 정수가 삽입될 수 있음을 참고하기 바란다. ‘D 1’는 Q에서 최댓값을 삭제하는 연산을 의미하며, ‘D -1’는 Q 에서 최솟값을 삭제하는 연산을 의미한다. 최댓값(최솟값)을 삭제하는 연산에서 최댓값(최솟값)이 둘 이상인 경우, 하나만 삭제됨을 유념하기 바란다.
만약 Q가 비어있는데 적용할 연산이 ‘D’라면 이 연산은 무시해도 좋다. Q에 저장될 모든 정수는 -231 이상 231 미만인 정수이다.
출력
출력은 표준출력을 사용한다. 각 테스트 데이터에 대해, 모든 연산을 처리한 후 Q에 남아 있는 값 중 최댓값과 최솟값을 출력하라. 두 값은 한 줄에 출력하되 하나의 공백으로 구분하라. 만약 Q가 비어있다면 ‘EMPTY’를 출력하라.
제한
예제 입력 1
복사
2
7
I 16
I -5643
D -1
D 1
D 1
I 123
D -1
9
I -45
I 653
D 1
I -642
I 45
I 97
D 1
D -1
I 333
예제 출력 1
복사
EMPTY
333 -45
힌트
W3sicHJvYmxlbV9pZCI6Ijc2NjIiLCJwcm9ibGVtX2xhbmciOiIwIiwidGl0bGUiOiJcdWM3NzRcdWM5MTEgXHVjNmIwXHVjMTIwXHVjMjFjXHVjNzA0IFx1ZDA1MCIsImRlc2NyaXB0aW9uIjoiPHA+XHVjNzc0XHVjOTExIFx1YzZiMFx1YzEyMFx1YzIxY1x1YzcwNCBcdWQwNTAoZHVhbCBwcmlvcml0eSBxdWV1ZSlcdWIyOTQgXHVjODA0XHVkNjE1XHVjODAxXHVjNzc4IFx1YzZiMFx1YzEyMFx1YzIxY1x1YzcwNCBcdWQwNTBcdWNjOThcdWI3ZmMgXHViMzcwXHVjNzc0XHVkMTMwXHViOTdjIFx1YzBiZFx1Yzc4NSwgXHVjMGFkXHVjODFjXHVkNTYwIFx1YzIxOCBcdWM3ODhcdWIyOTQgXHVjNzkwXHViOGNjIFx1YWQ2Y1x1Yzg3MFx1Yzc3NFx1YjJlNC4gXHVjODA0XHVkNjE1XHVjODAxXHVjNzc4IFx1ZDA1MFx1YzY0MFx1Yzc1OCBcdWNjMjhcdWM3NzRcdWM4MTBcdWM3NDAgXHViMzcwXHVjNzc0XHVkMTMwXHViOTdjIFx1YzBhZFx1YzgxY1x1ZDU2MCBcdWI1NGMgXHVjNWYwXHVjMGIwKG9wZXJhdGlvbikgXHViYTg1XHViODM5XHVjNWQwIFx1YjUzMFx1Yjc3YyBcdWM2YjBcdWMxMjBcdWMyMWNcdWM3MDRcdWFjMDAgXHVhYzAwXHVjN2E1IFx1YjE5Mlx1Yzc0MCBcdWIzNzBcdWM3NzRcdWQxMzAgXHViNjEwXHViMjk0IFx1YWMwMFx1YzdhNSBcdWIwYWVcdWM3NDAgXHViMzcwXHVjNzc0XHVkMTMwIFx1YzkxMSBcdWQ1NThcdWIwOThcdWI5N2MgXHVjMGFkXHVjODFjXHVkNTU4XHViMjk0IFx1YzgxMFx1Yzc3NFx1YjJlNC4gXHVjNzc0XHVjOTExIFx1YzZiMFx1YzEyMFx1YzIxY1x1YzcwNCBcdWQwNTBcdWI5N2MgXHVjNzA0XHVkNTc0XHVjMTIwIFx1YjQ1MCBcdWFjMDBcdWM5YzAgXHVjNWYwXHVjMGIwXHVjNzc0IFx1YzBhY1x1YzZhOVx1YjQxOFx1YjI5NFx1YjM3MCwgXHVkNTU4XHViMDk4XHViMjk0IFx1YjM3MFx1Yzc3NFx1ZDEzMFx1Yjk3YyBcdWMwYmRcdWM3ODVcdWQ1NThcdWIyOTQgXHVjNWYwXHVjMGIwXHVjNzc0XHVhY2UwIFx1YjJlNFx1Yjk3OCBcdWQ1NThcdWIwOThcdWIyOTQgXHViMzcwXHVjNzc0XHVkMTMwXHViOTdjIFx1YzBhZFx1YzgxY1x1ZDU1OFx1YjI5NCBcdWM1ZjBcdWMwYjBcdWM3NzRcdWIyZTQuIFx1YjM3MFx1Yzc3NFx1ZDEzMFx1Yjk3YyBcdWMwYWRcdWM4MWNcdWQ1NThcdWIyOTQgXHVjNWYwXHVjMGIwXHVjNzQwIFx1YjYxMCBcdWI0NTAgXHVhYzAwXHVjOWMwXHViODVjIFx1YWQ2Y1x1YmQ4NFx1YjQxOFx1YjI5NFx1YjM3MCBcdWQ1NThcdWIwOThcdWIyOTQgXHVjNmIwXHVjMTIwXHVjMjFjXHVjNzA0XHVhYzAwIFx1YWMwMFx1YzdhNSBcdWIxOTJcdWM3NDAgXHVhYzgzXHVjNzQ0IFx1YzBhZFx1YzgxY1x1ZDU1OFx1YWUzMCBcdWM3MDRcdWQ1NWMgXHVhYzgzXHVjNzc0XHVhY2UwIFx1YjJlNFx1Yjk3OCBcdWQ1NThcdWIwOThcdWIyOTQgXHVjNmIwXHVjMTIwXHVjMjFjXHVjNzA0XHVhYzAwIFx1YWMwMFx1YzdhNSBcdWIwYWVcdWM3NDAgXHVhYzgzXHVjNzQ0IFx1YzBhZFx1YzgxY1x1ZDU1OFx1YWUzMCBcdWM3MDRcdWQ1NWMgXHVhYzgzXHVjNzc0XHViMmU0LiA8XC9wPlxyXG5cclxuPHA+XHVjODE1XHVjMjE4XHViOWNjIFx1YzgwMFx1YzdhNVx1ZDU1OFx1YjI5NCBcdWM3NzRcdWM5MTEgXHVjNmIwXHVjMTIwXHVjMjFjXHVjNzA0IFx1ZDA1MCBRXHVhYzAwIFx1Yzc4OFx1YjJlNFx1YWNlMCBcdWFjMDBcdWM4MTVcdWQ1NThcdWM3OTAuIFFcdWM1ZDAgXHVjODAwXHVjN2E1XHViNDFjIFx1YWMwMSBcdWM4MTVcdWMyMThcdWM3NTggXHVhYzEyIFx1Yzc5MFx1Y2NiNFx1Yjk3YyBcdWM2YjBcdWMxMjBcdWMyMWNcdWM3MDRcdWI3N2NcdWFjZTAgXHVhYzA0XHVjOGZjXHVkNTU4XHVjNzkwLiA8XC9wPlxyXG5cclxuPHA+UVx1YzVkMCBcdWM4MDFcdWM2YTlcdWI0MjAgXHVjNzdjXHViODI4XHVjNzU4IFx1YzVmMFx1YzBiMFx1Yzc3NCBcdWM4ZmNcdWM1YjRcdWM5YzggXHViNTRjIFx1Yzc3NFx1Yjk3YyBcdWNjOThcdWI5YWNcdWQ1NWMgXHVkNmM0IFx1Y2Q1Y1x1Yzg4NVx1YzgwMVx1YzczY1x1Yjg1YyBRXHVjNWQwIFx1YzgwMFx1YzdhNVx1YjQxYyBcdWIzNzBcdWM3NzRcdWQxMzAgXHVjOTExIFx1Y2Q1Y1x1YjMxM1x1YWMxMlx1YWNmYyBcdWNkNWNcdWMxOWZcdWFjMTJcdWM3NDQgXHVjZDljXHViODI1XHVkNTU4XHViMjk0IFx1ZDUwNFx1Yjg1Y1x1YWRmOFx1YjdhOFx1Yzc0NCBcdWM3OTFcdWMxMzFcdWQ1NThcdWI3N2MuPFwvcD5cclxuIiwiaW5wdXQiOiI8cD5cdWM3ODVcdWI4MjUgXHViMzcwXHVjNzc0XHVkMTMwXHViMjk0IFx1ZDQ1Y1x1YzkwMFx1Yzc4NVx1YjgyNVx1Yzc0NCBcdWMwYWNcdWM2YTlcdWQ1NWNcdWIyZTQuIFx1Yzc4NVx1YjgyNVx1Yzc0MCBUXHVhYzFjXHVjNzU4IFx1ZDE0Y1x1YzJhNFx1ZDJiOCBcdWIzNzBcdWM3NzRcdWQxMzBcdWI4NWMgXHVhZDZjXHVjMTMxXHViNDFjXHViMmU0LiBcdWM3ODVcdWI4MjVcdWM3NTggXHVjY2FiIFx1YmM4OFx1YzlmOCBcdWM5MDRcdWM1ZDBcdWIyOTQgXHVjNzg1XHViODI1IFx1YjM3MFx1Yzc3NFx1ZDEzMFx1Yzc1OCBcdWMyMThcdWI5N2MgXHViMDk4XHVkMGMwXHViMGI0XHViMjk0IFx1YzgxNVx1YzIxOCBUXHVhYzAwIFx1YzhmY1x1YzViNFx1YzljNFx1YjJlNC4gXHVhYzAxIFx1ZDE0Y1x1YzJhNFx1ZDJiOCBcdWIzNzBcdWM3NzRcdWQxMzBcdWM3NTggXHVjY2FiXHVjOWY4IFx1YzkwNFx1YzVkMFx1YjI5NCBRXHVjNWQwIFx1YzgwMVx1YzZhOVx1ZDU2MCBcdWM1ZjBcdWMwYjBcdWM3NTggXHVhYzFjXHVjMjE4XHViOTdjIFx1YjA5OFx1ZDBjMFx1YjBiNFx1YjI5NCBcdWM4MTVcdWMyMTggayAoayAmbGU7IDEsMDAwLDAwMClcdWFjMDAgXHVjOGZjXHVjNWI0XHVjOWM0XHViMmU0LiBcdWM3NzRcdWM1YjRcdWM5YzBcdWIyOTQgayBcdWM5MDQgXHVhYzAxXHVhYzAxXHVjNWQ0IFx1YzVmMFx1YzBiMFx1Yzc0NCBcdWIwOThcdWQwYzBcdWIwYjRcdWIyOTQgXHViYjM4XHVjNzkwKCZsc3F1bztEJnJzcXVvOyBcdWI2MTBcdWIyOTQgJmxzcXVvO0kmcnNxdW87KVx1YzY0MCBcdWM4MTVcdWMyMTggblx1Yzc3NCBcdWM4ZmNcdWM1YjRcdWM5YzRcdWIyZTQuICZsc3F1bztJIG4mcnNxdW87XHVjNzQwIFx1YzgxNVx1YzIxOCBuXHVjNzQ0IFFcdWM1ZDAgXHVjMGJkXHVjNzg1XHVkNTU4XHViMjk0IFx1YzVmMFx1YzBiMFx1Yzc0NCBcdWM3NThcdWJiZjhcdWQ1NWNcdWIyZTQuIFx1YjNkOVx1Yzc3Y1x1ZDU1YyBcdWM4MTVcdWMyMThcdWFjMDAgXHVjMGJkXHVjNzg1XHViNDIwIFx1YzIxOCBcdWM3ODhcdWM3NGNcdWM3NDQgXHVjYzM4XHVhY2UwXHVkNTU4XHVhZTMwIFx1YmMxNFx1Yjc4MFx1YjJlNC4gJmxzcXVvO0QgMSZyc3F1bztcdWIyOTQgUVx1YzVkMFx1YzExYyBcdWNkNWNcdWIzMTNcdWFjMTJcdWM3NDQgXHVjMGFkXHVjODFjXHVkNTU4XHViMjk0IFx1YzVmMFx1YzBiMFx1Yzc0NCBcdWM3NThcdWJiZjhcdWQ1NThcdWJhNzAsICZsc3F1bztEIC0xJnJzcXVvO1x1YjI5NCBRIFx1YzVkMFx1YzExYyBcdWNkNWNcdWMxOWZcdWFjMTJcdWM3NDQgXHVjMGFkXHVjODFjXHVkNTU4XHViMjk0IFx1YzVmMFx1YzBiMFx1Yzc0NCBcdWM3NThcdWJiZjhcdWQ1NWNcdWIyZTQuIFx1Y2Q1Y1x1YjMxM1x1YWMxMihcdWNkNWNcdWMxOWZcdWFjMTIpXHVjNzQ0IFx1YzBhZFx1YzgxY1x1ZDU1OFx1YjI5NCBcdWM1ZjBcdWMwYjBcdWM1ZDBcdWMxMWMgXHVjZDVjXHViMzEzXHVhYzEyKFx1Y2Q1Y1x1YzE5Zlx1YWMxMilcdWM3NzQgXHViNDU4IFx1Yzc3NFx1YzBjMVx1Yzc3OCBcdWFjYmRcdWM2YjAsIFx1ZDU1OFx1YjA5OFx1YjljYyBcdWMwYWRcdWM4MWNcdWI0MjhcdWM3NDQgXHVjNzIwXHViMTUwXHVkNTU4XHVhZTMwIFx1YmMxNFx1Yjc4MFx1YjJlNC48XC9wPlxyXG5cclxuPHA+XHViOWNjXHVjNTdkIFFcdWFjMDAgXHViZTQ0XHVjNWI0XHVjNzg4XHViMjk0XHViMzcwIFx1YzgwMVx1YzZhOVx1ZDU2MCBcdWM1ZjBcdWMwYjBcdWM3NzQgJmxzcXVvO0QmcnNxdW87XHViNzdjXHViYTc0IFx1Yzc3NCBcdWM1ZjBcdWMwYjBcdWM3NDAgXHViYjM0XHVjMmRjXHVkNTc0XHViM2M0IFx1Yzg4Ylx1YjJlNC4gUVx1YzVkMCBcdWM4MDBcdWM3YTVcdWI0MjAgXHViYWE4XHViNGUwIFx1YzgxNVx1YzIxOFx1YjI5NCAtMjxzdXA+MzE8XC9zdXA+IFx1Yzc3NFx1YzBjMSAyPHN1cD4zMTxcL3N1cD4gXHViYmY4XHViOWNjXHVjNzc4IFx1YzgxNVx1YzIxOFx1Yzc3NFx1YjJlNC4gPFwvcD5cclxuIiwib3V0cHV0IjoiPHA+XHVjZDljXHViODI1XHVjNzQwIFx1ZDQ1Y1x1YzkwMFx1Y2Q5Y1x1YjgyNVx1Yzc0NCBcdWMwYWNcdWM2YTlcdWQ1NWNcdWIyZTQuIFx1YWMwMSBcdWQxNGNcdWMyYTRcdWQyYjggXHViMzcwXHVjNzc0XHVkMTMwXHVjNWQwIFx1YjMwMFx1ZDU3NCwgXHViYWE4XHViNGUwIFx1YzVmMFx1YzBiMFx1Yzc0NCBcdWNjOThcdWI5YWNcdWQ1NWMgXHVkNmM0IFFcdWM1ZDAgXHViMGE4XHVjNTQ0IFx1Yzc4OFx1YjI5NCBcdWFjMTIgXHVjOTExIFx1Y2Q1Y1x1YjMxM1x1YWMxMlx1YWNmYyBcdWNkNWNcdWMxOWZcdWFjMTJcdWM3NDQgXHVjZDljXHViODI1XHVkNTU4XHViNzdjLiBcdWI0NTAgXHVhYzEyXHVjNzQwIFx1ZDU1YyBcdWM5MDRcdWM1ZDAgXHVjZDljXHViODI1XHVkNTU4XHViNDE4IFx1ZDU1OFx1YjA5OFx1Yzc1OCBcdWFjZjVcdWJjMzFcdWM3M2NcdWI4NWMgXHVhZDZjXHViZDg0XHVkNTU4XHViNzdjLiBcdWI5Y2NcdWM1N2QgUVx1YWMwMCBcdWJlNDRcdWM1YjRcdWM3ODhcdWIyZTRcdWJhNzQgJmxzcXVvO0VNUFRZJnJzcXVvO1x1Yjk3YyBcdWNkOWNcdWI4MjVcdWQ1NThcdWI3N2MuPFwvcD5cclxuIiwiaGludCI6IiIsIm9yaWdpbmFsIjoiMCIsImh0bWxfdGl0bGUiOiIwIiwicHJvYmxlbV9sYW5nX3Rjb2RlIjoiS29yZWFuIn0seyJwcm9ibGVtX2lkIjoiNzY2MiIsInByb2JsZW1fbGFuZyI6IjEiLCJ0aXRsZSI6IkR1YWwgUHJpb3JpdHkgUXVldWUiLCJkZXNjcmlwdGlvbiI6IjxwPkEgZHVhbCBwcmlvcml0eSBxdWV1ZSBpcyBhIGRhdGEgc3RydWN0dXJlIGluIHdoaWNoIHdlIGNhbiBpbnNlcnQgYW5kIGRlbGV0ZSBkYXRhIGxpa2UgYSB0eXBpY2FsIHF1ZXVlLiBJdHMgZGlmZmVyZW5jZSBmcm9tIGEgdHlwaWNhbCBxdWV1ZSBpcyB0aGF0IHdoZW4gYW4gaXRlbSBpcyB0byBiZSBkZWxldGVkIGZyb20gdGhlIHF1ZXVlIGVpdGhlciBhbiBpdGVtIHdpdGggaGlnaGVzdCBwcmlvcml0eSBvciB3aXRoIGxvd2VzdCBwcmlvcml0eSBpbiBpdCBpcyBkZWxldGVkIGFjY29yZGluZyB0byB0aGUgb3BlcmF0aW9uIGZvciBkZWxldGlvbi4gVGhlcmUgYXJlIHR3byBvcGVyYXRpb25zIGZvciB0aGUgZHVhbCBwcmlvcml0eSBxdWV1ZSwgb25lIGZvciBpbnNlcnRpbmcgYW4gaXRlbSBpbnRvIGl0LCB0aGUgb3RoZXIgZm9yIGRlbGV0aW5nIGFuIGl0ZW0gZnJvbSBpdC4gRGVsZXRpb24gb3BlcmF0aW9uIGl0c2VsZiBoYXMgdHdvIHBhcmFtZXRlcnM6IG9uZSBmb3IgZGVsZXRpbmcgYW4gaXRlbSB3aXRoIGhpZ2hlc3QgcHJpb3JpdHkgZnJvbSBpdCwgYW5kIHRoZSBvdGhlciBmb3IgZGVsZXRpbmcgYW4gaXRlbSB3aXRoIGxvd2VzdCBwcmlvcml0eS4mbmJzcDs8XC9wPlxyXG5cclxuPHA+U3VwcG9zZSB0aGVyZSBpcyBhIGR1YWwgcHJpb3JpdHkgcXVldWUgUSB3aGljaCBzdG9yZXMgaW50ZWdlcnMgb25seS4gVGhlIHZhbHVlIG9mIGVhY2ggaW50ZWdlciBpbiBRIGlzIGNvbnNpZGVyZWQgdGhlIHByaW9yaXR5IG9mIGl0c2VsZi4mbmJzcDs8XC9wPlxyXG5cclxuPHA+R2l2ZW4gYSBsaXN0IG9mIG9wZXJhdGlvbnMsIHdyaXRlIGEgcHJvZ3JhbSB0aGF0IHByb2Nlc3NlcyB0aGUgb3BlcmF0aW9ucyBmb3IgUSBhbmQgc2hvd3MgdGhlIG1pbmltdW0gYW5kIG1heGltdW0gbnVtYmVycyBpbiBRIGFmdGVyIGZpbmlzaGluZyB0aGUgb3BlcmF0aW9ucy4mbmJzcDs8XC9wPlxyXG4iLCJpbnB1dCI6IjxwPllvdXIgcHJvZ3JhbSBpcyB0byByZWFkIGZyb20gc3RhbmRhcmQgaW5wdXQuIFRoZSBpbnB1dCBjb25zaXN0cyBvZiBUIHRlc3QgY2FzZXMuIFRoZSBudW1iZXIgb2YgdGVzdCBjYXNlcyBUIGlzIGdpdmVuIGluIHRoZSBmaXJzdCBsaW5lIG9mIHRoZSBpbnB1dC4gRWFjaCB0ZXN0IGNhc2Ugc3RhcnRzIHdpdGggYSBsaW5lIGNvbnRhaW5pbmcgYW4gaW50ZWdlciBrIChrICZsZTsgMSwwMDAsMDAwKSwgdGhlIG51bWJlciBvZiBvcGVyYXRpb25zIGZvciBRLiBJbiB0aGUgbmV4dCBrIGxpbmVzLCBlYWNoIGxpbmUgY29udGFpbnMgZWl0aGVyICZsc3F1bztEJnJzcXVvOyBvciAmbHNxdW87SSZyc3F1bzsgZm9sbG93ZWQgYnkgYW4gaW50ZWdlciBuLiBPcGVyYXRpb24gJmxzcXVvO0kgbiZyc3F1bzsgbWVhbnMgaW5zZXJ0aW5nIGludGVnZXIgbiBpbnRvIFEuIE5vdGUgdGhhdCB0aGUgc2FtZSBpbnRlZ2VycyBjYW4gYmUgaW5zZXJ0ZWQgaW50byBRLiBPcGVyYXRpb24gJmxzcXVvO0QgMSZyc3F1bzsgbWVhbnMgZGVsZXRpbmcgdGhlIG1heGltdW0gbnVtYmVyIGZyb20gUS4gV2hpbGUgT3BlcmF0aW9uICZsc3F1bztEIC0xJnJzcXVvOyBpcyB1c2VkIHRvIGRlbGV0ZSB0aGUgbWluaW11bSBudW1iZXIgZnJvbSBRLiBJZiB0aGVyZSBhcmUgdHdvIG9yIG1vcmUgbWF4aW1hIChtaW5pbWEpIGluIFEgd2hlbiB0aGUgb3BlcmF0aW9uIGlzICZsc3F1bztEIDEmcnNxdW87KCZsc3F1bztEIC0xJnJzcXVvOyksIG9ubHkgb25lIG9mIHRoZW0gaXMgZGVsZXRlZC4mbmJzcDs8XC9wPlxyXG5cclxuPHA+SWYgUSBpcyBlbXB0eSB3aGVuIHRoZSBvcGVyYXRpb24gaXMgJmxzcXVvO0QmcnNxdW87IHlvdSBjYW4gaWdub3JlIGl0LiBFYWNoIGlucHV0IHRvIGJlIGluc2VydGVkIGludG8gUSBpcyBhIGFuIGludGVnZXIgYmV0d2VlbiAtMjxzdXA+MzE8XC9zdXA+Jm5ic3A7YW5kIDI8c3VwPjMxPFwvc3VwPi0xLCBpbmNsdXNpdmUuPFwvcD5cclxuIiwib3V0cHV0IjoiPHA+WW91ciBwcm9ncmFtIGlzIHRvIHdyaXRlIHRvIHN0YW5kYXJkIG91dHB1dC4gRm9yIGVhY2ggdGVzdCBjYXNlLCBwcmludCB0aGUgbWF4aW11bSBhbmQgdGhlIG1pbmltdW0gbnVtYmVycyBhbW9uZyB0aG9zZSB3aGljaCByZW1haW4gaW4gUS4gVGhlIHR3byBudW1iZXJzIHNob3VsZCBiZSBwcmludGVkIGluIGEgbGluZSBzZXBhcmF0ZWQgYnkgYSBibGFuay4gSWYgUSBpcyBlbXB0eSBhdCB0aGUgZW5kLCBwcmludCAmbHNxdW87RU1QVFkmcnNxdW87LiZuYnNwOzxcL3A+XHJcbiIsImhpbnQiOiIiLCJvcmlnaW5hbCI6IjEiLCJodG1sX3RpdGxlIjoiMCIsInByb2JsZW1fbGFuZ190Y29kZSI6IkVuZ2xpc2gifV0=
-
AC
출처 : AC
Solution
Python
import sys
input = sys.stdin.readline
# list를 슬라이싱하면 무조건 시간초과!
from collections import deque
if __name__ == '__main__':
T = int(input())
for _ in range(T):
P = input().rstrip()
n = int(input())
x = input().rstrip()
# 빈 배열 입력해도 문자열이라 1개는 들어가므로, 예외처리해줌
if x=='[]': x=deque([])
else: x = deque(x[1:-1].split(','))
r = 0
for p in P:
# deque를 사용해도 reverse연산은 많은 시간초과를 야기함
if p=='R': r+=1 # 누적합해주고 별도 판단해준다.
# D 연산해야할 경우,
else:
# 없앨 원소가 없으면 에러!
if len(x)<=0:
x = 'error'
break
# 뒤집어져있다면 뒤쪽 원소 삭제
if r%2==1: x.pop()
# 뒤집히지 않았다면 앞쪽 원소 삭제
else: x.popleft()
# 에러 발생했다면 에러만 띄워줌
if x == 'error': print(x)
else: # 만약 뒤집어져야하면 한번 뒤집고,
if r%2==1: x.reverse()
# 출력 요구조건에 맞춰서 print해준다.
print('[',end='')
print(*x, sep=',', end='')
print(']')
문제
선영이는 주말에 할 일이 없어서 새로운 언어 AC를 만들었다. AC는 정수 배열에 연산을 하기 위해 만든 언어이다. 이 언어에는 두 가지 함수 R(뒤집기)과 D(버리기)가 있다.
함수 R은 배열에 있는 수의 순서를 뒤집는 함수이고, D는 첫 번째 수를 버리는 함수이다. 배열이 비어있는데 D를 사용한 경우에는 에러가 발생한다.
함수는 조합해서 한 번에 사용할 수 있다. 예를 들어, "AB"는 A를 수행한 다음에 바로 이어서 B를 수행하는 함수이다. 예를 들어, "RDD"는 배열을 뒤집은 다음 처음 두 수를 버리는 함수이다.
배열의 초기값과 수행할 함수가 주어졌을 때, 최종 결과를 구하는 프로그램을 작성하시오.
입력
첫째 줄에 테스트 케이스의 개수 T가 주어진다. T는 최대 100이다.
각 테스트 케이스의 첫째 줄에는 수행할 함수 p가 주어진다. p의 길이는 1보다 크거나 같고, 100,000보다 작거나 같다.
다음 줄에는 배열에 들어있는 수의 개수 n이 주어진다. (0 ≤ n ≤ 100,000)
다음 줄에는 [x1,...,xn]과 같은 형태로 배열에 들어있는 정수가 주어진다. (1 ≤ xi ≤ 100)
전체 테스트 케이스에 주어지는 p의 길이의 합과 n의 합은 70만을 넘지 않는다.
출력
각 테스트 케이스에 대해서, 입력으로 주어진 정수 배열에 함수를 수행한 결과를 출력한다. 만약, 에러가 발생한 경우에는 error를 출력한다.
제한
예제 입력 1
복사
4
RDD
4
[1,2,3,4]
DD
1
[42]
RRD
6
[1,1,2,3,5,8]
D
0
[]
예제 출력 1
복사
[2,1]
error
[1,2,3,5,8]
error
힌트
W3sicHJvYmxlbV9pZCI6IjU0MzAiLCJwcm9ibGVtX2xhbmciOiIwIiwidGl0bGUiOiJBQyIsImRlc2NyaXB0aW9uIjoiPHA+XHVjMTIwXHVjNjAxXHVjNzc0XHViMjk0IFx1YzhmY1x1YjlkMFx1YzVkMCBcdWQ1NjAgXHVjNzdjXHVjNzc0IFx1YzVjNlx1YzViNFx1YzExYyBcdWMwYzhcdWI4NWNcdWM2YjQgXHVjNWI4XHVjNWI0IEFDXHViOTdjIFx1YjljY1x1YjRlNFx1YzVjOFx1YjJlNC4gQUNcdWIyOTQgXHVjODE1XHVjMjE4IFx1YmMzMFx1YzVmNFx1YzVkMCBcdWM1ZjBcdWMwYjBcdWM3NDQgXHVkNTU4XHVhZTMwIFx1YzcwNFx1ZDU3NCBcdWI5Y2NcdWI0ZTAgXHVjNWI4XHVjNWI0XHVjNzc0XHViMmU0LiBcdWM3NzQgXHVjNWI4XHVjNWI0XHVjNWQwXHViMjk0IFx1YjQ1MCBcdWFjMDBcdWM5YzAgXHVkNTY4XHVjMjE4IFIoXHViNGE0XHVjOWQxXHVhZTMwKVx1YWNmYyBEKFx1YmM4NFx1YjlhY1x1YWUzMClcdWFjMDAgXHVjNzg4XHViMmU0LjxcL3A+XHJcblxyXG48cD5cdWQ1NjhcdWMyMTggUlx1Yzc0MCBcdWJjMzBcdWM1ZjRcdWM1ZDAgXHVjNzg4XHViMjk0IFx1YzIxOFx1Yzc1OCBcdWMyMWNcdWMxMWNcdWI5N2MgXHViNGE0XHVjOWQxXHViMjk0IFx1ZDU2OFx1YzIxOFx1Yzc3NFx1YWNlMCwgRFx1YjI5NCBcdWNjYWIgXHViYzg4XHVjOWY4IFx1YzIxOFx1Yjk3YyBcdWJjODRcdWI5YWNcdWIyOTQgXHVkNTY4XHVjMjE4XHVjNzc0XHViMmU0LiBcdWJjMzBcdWM1ZjRcdWM3NzQgXHViZTQ0XHVjNWI0XHVjNzg4XHViMjk0XHViMzcwIERcdWI5N2MgXHVjMGFjXHVjNmE5XHVkNTVjIFx1YWNiZFx1YzZiMFx1YzVkMFx1YjI5NCBcdWM1ZDBcdWI3ZWNcdWFjMDAgXHViYzFjXHVjMGRkXHVkNTVjXHViMmU0LjxcL3A+XHJcblxyXG48cD5cdWQ1NjhcdWMyMThcdWIyOTQgXHVjODcwXHVkNTY5XHVkNTc0XHVjMTFjIFx1ZDU1YyBcdWJjODhcdWM1ZDAgXHVjMGFjXHVjNmE5XHVkNTYwIFx1YzIxOCBcdWM3ODhcdWIyZTQuIFx1YzYwOFx1Yjk3YyBcdWI0ZTRcdWM1YjQsICZxdW90O0FCJnF1b3Q7XHViMjk0IEFcdWI5N2MgXHVjMjE4XHVkNTg5XHVkNTVjIFx1YjJlNFx1Yzc0Y1x1YzVkMCBcdWJjMTRcdWI4NWMgXHVjNzc0XHVjNWI0XHVjMTFjIEJcdWI5N2MgXHVjMjE4XHVkNTg5XHVkNTU4XHViMjk0IFx1ZDU2OFx1YzIxOFx1Yzc3NFx1YjJlNC4gXHVjNjA4XHViOTdjIFx1YjRlNFx1YzViNCwgJnF1b3Q7UkREJnF1b3Q7XHViMjk0IFx1YmMzMFx1YzVmNFx1Yzc0NCBcdWI0YTRcdWM5ZDFcdWM3NDAgXHViMmU0XHVjNzRjIFx1Y2M5OFx1Yzc0YyBcdWI0NTAgXHVjMjE4XHViOTdjIFx1YmM4NFx1YjlhY1x1YjI5NCBcdWQ1NjhcdWMyMThcdWM3NzRcdWIyZTQuPFwvcD5cclxuXHJcbjxwPlx1YmMzMFx1YzVmNFx1Yzc1OCBcdWNkMDhcdWFlMzBcdWFjMTJcdWFjZmMgXHVjMjE4XHVkNTg5XHVkNTYwIFx1ZDU2OFx1YzIxOFx1YWMwMCBcdWM4ZmNcdWM1YjRcdWM4NGNcdWM3NDQgXHViNTRjLCBcdWNkNWNcdWM4ODUgXHVhY2IwXHVhY2ZjXHViOTdjIFx1YWQ2Y1x1ZDU1OFx1YjI5NCBcdWQ1MDRcdWI4NWNcdWFkZjhcdWI3YThcdWM3NDQgXHVjNzkxXHVjMTMxXHVkNTU4XHVjMmRjXHVjNjI0LjxcL3A+XHJcbiIsImlucHV0IjoiPHA+XHVjY2FiXHVjOWY4IFx1YzkwNFx1YzVkMCBcdWQxNGNcdWMyYTRcdWQyYjggXHVjZjAwXHVjNzc0XHVjMmE0XHVjNzU4IFx1YWMxY1x1YzIxOCBUXHVhYzAwIFx1YzhmY1x1YzViNFx1YzljNFx1YjJlNC4gVFx1YjI5NCBcdWNkNWNcdWIzMDAgMTAwXHVjNzc0XHViMmU0LjxcL3A+XHJcblxyXG48cD5cdWFjMDEgXHVkMTRjXHVjMmE0XHVkMmI4IFx1Y2YwMFx1Yzc3NFx1YzJhNFx1Yzc1OCBcdWNjYWJcdWM5ZjggXHVjOTA0XHVjNWQwXHViMjk0IFx1YzIxOFx1ZDU4OVx1ZDU2MCBcdWQ1NjhcdWMyMTggcFx1YWMwMCBcdWM4ZmNcdWM1YjRcdWM5YzRcdWIyZTQuIHBcdWM3NTggXHVhZTM4XHVjNzc0XHViMjk0IDFcdWJjZjRcdWIyZTQgXHVkMDZjXHVhYzcwXHViMDk4IFx1YWMxOVx1YWNlMCwgMTAwLDAwMFx1YmNmNFx1YjJlNCBcdWM3OTFcdWFjNzBcdWIwOTggXHVhYzE5XHViMmU0LjxcL3A+XHJcblxyXG48cD5cdWIyZTRcdWM3NGMgXHVjOTA0XHVjNWQwXHViMjk0IFx1YmMzMFx1YzVmNFx1YzVkMCBcdWI0ZTRcdWM1YjRcdWM3ODhcdWIyOTQgXHVjMjE4XHVjNzU4IFx1YWMxY1x1YzIxOCBuXHVjNzc0IFx1YzhmY1x1YzViNFx1YzljNFx1YjJlNC4gKDAgJmxlOyBuICZsZTsgMTAwLDAwMCk8XC9wPlxyXG5cclxuPHA+XHViMmU0XHVjNzRjIFx1YzkwNFx1YzVkMFx1YjI5NCBbeDxzdWI+MTxcL3N1Yj4sLi4uLHg8c3ViPm48XC9zdWI+XVx1YWNmYyBcdWFjMTlcdWM3NDAgXHVkNjE1XHVkMGRjXHViODVjIFx1YmMzMFx1YzVmNFx1YzVkMCBcdWI0ZTRcdWM1YjRcdWM3ODhcdWIyOTQgXHVjODE1XHVjMjE4XHVhYzAwIFx1YzhmY1x1YzViNFx1YzljNFx1YjJlNC4gKDEgJmxlOyB4PHN1Yj5pPFwvc3ViPiAmbGU7IDEwMCk8XC9wPlxyXG5cclxuPHA+XHVjODA0XHVjY2I0IFx1ZDE0Y1x1YzJhNFx1ZDJiOCBcdWNmMDBcdWM3NzRcdWMyYTRcdWM1ZDAgXHVjOGZjXHVjNWI0XHVjOWMwXHViMjk0IHBcdWM3NTggXHVhZTM4XHVjNzc0XHVjNzU4IFx1ZDU2OVx1YWNmYyBuXHVjNzU4IFx1ZDU2OVx1Yzc0MCA3MFx1YjljY1x1Yzc0NCBcdWIxMThcdWM5YzAgXHVjNTRhXHViMjk0XHViMmU0LjxcL3A+XHJcbiIsIm91dHB1dCI6IjxwPlx1YWMwMSBcdWQxNGNcdWMyYTRcdWQyYjggXHVjZjAwXHVjNzc0XHVjMmE0XHVjNWQwIFx1YjMwMFx1ZDU3NFx1YzExYywgXHVjNzg1XHViODI1XHVjNzNjXHViODVjIFx1YzhmY1x1YzViNFx1YzljNCBcdWM4MTVcdWMyMTggXHViYzMwXHVjNWY0XHVjNWQwIFx1ZDU2OFx1YzIxOFx1Yjk3YyBcdWMyMThcdWQ1ODlcdWQ1NWMgXHVhY2IwXHVhY2ZjXHViOTdjIFx1Y2Q5Y1x1YjgyNVx1ZDU1Y1x1YjJlNC4gXHViOWNjXHVjNTdkLCBcdWM1ZDBcdWI3ZWNcdWFjMDAgXHViYzFjXHVjMGRkXHVkNTVjIFx1YWNiZFx1YzZiMFx1YzVkMFx1YjI5NCBlcnJvclx1Yjk3YyBcdWNkOWNcdWI4MjVcdWQ1NWNcdWIyZTQuPFwvcD5cclxuIiwiaGludCI6IiIsIm9yaWdpbmFsIjoiMCIsImh0bWxfdGl0bGUiOiIwIiwicHJvYmxlbV9sYW5nX3Rjb2RlIjoiS29yZWFuIn0seyJwcm9ibGVtX2lkIjoiNTQzMCIsInByb2JsZW1fbGFuZyI6IjEiLCJ0aXRsZSI6IkludGVnZXIgTGlzdHMiLCJkZXNjcmlwdGlvbiI6IjxwPlRoZSBwcm9ncmFtbWluZyBsYW5ndWFnZSBCZXR0ZXIgQW5kIFBvcnRhYmxlIENvZGUgKEJBUEMpIGlzIGEgbGFuZ3VhZ2UgZm9yIHdvcmtpbmcgd2l0aCBsaXN0cyBvZiBpbnRlZ2Vycy4gVGhlIGxhbmd1YWdlIGhhcyB0d28gYnVpbHQtaW4gZnVuY3Rpb25zOiAmbHNxdW87UiZyc3F1bzsgKHJldmVyc2UpIGFuZCAmbHNxdW87RCZyc3F1bzsgKGRyb3ApLjxcL3A+XHJcblxyXG48cD5UaGUgZnVuY3Rpb24gJmxzcXVvO1ImcnNxdW87IHJldmVyc2VzIGl0cyBpbnB1dCBsaXN0LCBhbmQgJnJzcXVvO0QmcnNxdW87IGRyb3BzIHRoZSBmaXJzdCBlbGVtZW50IG9mIGl0cyBpbnB1dCBhbmQgcmV0dXJucyB0aGUgcmVzdCwgb3IgZ2l2ZXMgYW4gZXJyb3IgaW4gY2FzZSBpdHMgaW5wdXQgaXMgYW4gZW1wdHkgbGlzdC4gVG8gZ2V0IG1vcmUgYWR2YW5jZWQgYmVoYXZpb3IsIGZ1bmN0aW9ucyBjYW4gYmUgY29tcG9zZWQ6ICZsZHF1bztBQiZyZHF1bzsgaXMgdGhlIGZ1bmN0aW9uIHRoYXQgZmlyc3QgYXBwbGllcyAmbHNxdW87QSZyc3F1bzsgdG8gaXRzIGlucHV0IGFuZCB0aGVuICZsc3F1bztCJnJzcXVvOyB0byB0aGUgcmVzdWx0aW5nIGxpc3QuIEZvciBleGFtcGxlLCAmbGRxdW87UkREJnJkcXVvOyBpcyBhIGZ1bmN0aW9uIHRoYXQgcmV2ZXJzZXMgYSBsaXN0IGFuZCB0aGVuIGRyb3BzIHRoZSBmaXJzdCB0d28gZWxlbWVudHMuPFwvcD5cclxuXHJcbjxwPlVuZm9ydHVuYXRlbHksIG91ciBCQVBDIGludGVycHJldGVyIGhhcyBiaXQgcm90dGVkLCBzbyB3ZSBhc2sgeW91IHRvIHdyaXRlIGEgbmV3IG9uZS48XC9wPlxyXG5cclxuPHA+R2l2ZW4gYSBCQVBDIHByb2dyYW0gYW5kIGl0cyBpbnB1dCwgcmV0dXJuIGl0cyBvdXRwdXQgb3IgJmxkcXVvO2Vycm9yJnJkcXVvOyBpbiBjYXNlICZsc3F1bztEJnJzcXVvOyBpcyBhcHBsaWVkIHRvIGFuIGVtcHR5IGxpc3QuIExpc3RzIGFyZSByZXByZXNlbnRlZCBhcyB0aGUgY2hhcmFjdGVyICZsc3F1bztbJnJzcXVvOyBmb2xsb3dlZCBieSBhIGNvbW1hLXNlcGFyYXRlZCBsaXN0IG9mIGludGVnZXJzIGZvbGxvd2VkIGJ5IHRoZSBjaGFyYWN0ZXIgJmxzcXVvO10mcnNxdW87LiBOb3RpY2UgdGhhdCB0aGUgaW5wdXQgYW5kIG91dHB1dCBsaXN0cyBjYW4gYmUgcXVpdGUgbG9uZy48XC9wPlxyXG4iLCJpbnB1dCI6IjxwPk9uIHRoZSBmaXJzdCBsaW5lIG9uZSBwb3NpdGl2ZSBudW1iZXI6IHRoZSBudW1iZXIgb2YgdGVzdCBjYXNlcywgYXQgbW9zdCAxMDAuIEFmdGVyIHRoYXQgcGVyIHRlc3QgY2FzZTo8XC9wPlxyXG5cclxuPHVsPlxyXG5cdDxsaT5vbmUgbGluZSB3aXRoIGEgc3RyaW5nIHAgKDEgXHUwMDE0JmxlOyBsZW5ndGgocCkgJmxlO1x1MDAxNCAxMDAgMDAwKTogYSBCQVBDIHByb2dyYW0sIGNvbnNpc3Rpbmcgb2YgdGhlPFwvbGk+XHJcblx0PGxpPmNoYXJhY3RlcnMgJmxzcXVvO1ImcnNxdW87IGFuZCAmbHNxdW87RCZyc3F1bzsuPFwvbGk+XHJcblx0PGxpPm9uZSBsaW5lIHdpdGggYW4gaW50ZWdlciBuICgwIFx1MDAxNCZsZTsgbiBcdTAwMTQmbGU7IDEwMCAwMDApOiB0aGUgbnVtYmVyIG9mIGVsZW1lbnRzIGluIHRoZSBpbnB1dC48XC9saT5cclxuXHQ8bGk+b25lIGxpbmUgd2l0aCBhIGxpc3Qgb2YgbiBpbnRlZ2VycyBpbiB0aGUgZm9ybSBbeDxzdWI+MTxcL3N1Yj4sIC4uLiwgeDxzdWI+bjxcL3N1Yj5dICgxICZsZTtcdTAwMTQgeDxzdWI+aTxcL3N1Yj4gJmxlO1x1MDAxNCAxMDApOiB0aGUgaW5wdXQgbGlzdDxcL2xpPlxyXG48XC91bD5cclxuIiwib3V0cHV0IjoiPHA+UGVyIHRlc3QgY2FzZTo8XC9wPlxyXG5cclxuPHVsPlxyXG5cdDxsaT5vbmUgbGluZSB3aXRoIHRoZSByZXN1bHRpbmcgaW50ZWdlciBsaXN0IG9yICZsZHF1bztlcnJvciZyZHF1bzsgaW4gY2FzZSBvZiBhbiBlcnJvci48XC9saT5cclxuPFwvdWw+XHJcbiIsImhpbnQiOiIiLCJvcmlnaW5hbCI6IjEiLCJodG1sX3RpdGxlIjoiMCIsInByb2JsZW1fbGFuZ190Y29kZSI6IkVuZ2xpc2gifV0=
-
-
두 수의 합
출처 : 두 수의 합
Solution
Python
import sys
input = sys.stdin.readline
if __name__ == '__main__':
n = int(input())
a = list(map(int, input().split()))
x = int(input())
a.sort() # 일단 정렬
# a의 인덱스 값(i<j), 양끝에서 조사한다!
i, j = 0, n-1
# 숫자쌍의 갯수
answer = 0
# i가 j보다 작을 때 작동하도록 함, 즉 두 인덱스값이 만나면 종료
while i<j:
# 두 숫자합이 x와 같다면,
if a[i]+a[j] == x:
answer += 1 # 더해주고
j -= 1 # j를 1 빼주거나, i를 1 더해주거나
# 두 숫자합이 x보다 작다면
elif a[i]+a[j] < x:
i += 1 # 합이 커져야하니 i+1
# 두 숫자합이 x보다 크다면
elif a[i]+a[j] > x:
j -= 1 # 합이 작아져야하니 j-1
print(answer)
문제
n개의 서로 다른 양의 정수 a1, a2, ..., an으로 이루어진 수열이 있다. ai의 값은 1보다 크거나 같고, 1000000보다 작거나 같은 자연수이다. 자연수 x가 주어졌을 때, ai + aj = x (1 ≤ i < j ≤ n)을 만족하는 (ai, aj)쌍의 수를 구하는 프로그램을 작성하시오.
입력
첫째 줄에 수열의 크기 n이 주어진다. 다음 줄에는 수열에 포함되는 수가 주어진다. 셋째 줄에는 x가 주어진다. (1 ≤ n ≤ 100000, 1 ≤ x ≤ 2000000)
출력
문제의 조건을 만족하는 쌍의 개수를 출력한다.
제한
예제 입력 1
복사
9
5 12 7 10 9 1 2 3 11
13
예제 출력 1
복사
3
힌트
W3sicHJvYmxlbV9pZCI6IjMyNzMiLCJwcm9ibGVtX2xhbmciOiIwIiwidGl0bGUiOiJcdWI0NTAgXHVjMjE4XHVjNzU4IFx1ZDU2OSIsImRlc2NyaXB0aW9uIjoiPHA+blx1YWMxY1x1Yzc1OCBcdWMxMWNcdWI4NWMgXHViMmU0XHViOTc4IFx1YzU5MVx1Yzc1OCBcdWM4MTVcdWMyMTggYTxzdWI+MTxcL3N1Yj4sIGE8c3ViPjI8XC9zdWI+LCAuLi4sIGE8c3ViPm48XC9zdWI+XHVjNzNjXHViODVjIFx1Yzc3NFx1YjhlOFx1YzViNFx1YzljNCBcdWMyMThcdWM1ZjRcdWM3NzQgXHVjNzg4XHViMmU0LiBhPHN1Yj5pPFwvc3ViPlx1Yzc1OCBcdWFjMTJcdWM3NDAgMVx1YmNmNFx1YjJlNCBcdWQwNmNcdWFjNzBcdWIwOTggXHVhYzE5XHVhY2UwLCAxMDAwMDAwXHViY2Y0XHViMmU0IFx1Yzc5MVx1YWM3MFx1YjA5OCBcdWFjMTlcdWM3NDAgXHVjNzkwXHVjNWYwXHVjMjE4XHVjNzc0XHViMmU0LiBcdWM3OTBcdWM1ZjBcdWMyMTggeFx1YWMwMCBcdWM4ZmNcdWM1YjRcdWM4NGNcdWM3NDQgXHViNTRjLCBhPHN1Yj5pPFwvc3ViPiArIGE8c3ViPmo8XC9zdWI+ID0geCAoMSAmbGU7IGkgJmx0OyBqICZsZTsgbilcdWM3NDQgXHViOWNjXHVjODcxXHVkNTU4XHViMjk0IChhPHN1Yj5pPFwvc3ViPiwgYTxzdWI+ajxcL3N1Yj4pXHVjMzBkXHVjNzU4IFx1YzIxOFx1Yjk3YyBcdWFkNmNcdWQ1NThcdWIyOTQgXHVkNTA0XHViODVjXHVhZGY4XHViN2E4XHVjNzQ0IFx1Yzc5MVx1YzEzMVx1ZDU1OFx1YzJkY1x1YzYyNC48XC9wPlxyXG4iLCJpbnB1dCI6IjxwPlx1Y2NhYlx1YzlmOCBcdWM5MDRcdWM1ZDAgXHVjMjE4XHVjNWY0XHVjNzU4IFx1ZDA2Y1x1YWUzMCBuXHVjNzc0IFx1YzhmY1x1YzViNFx1YzljNFx1YjJlNC4gXHViMmU0XHVjNzRjIFx1YzkwNFx1YzVkMFx1YjI5NCBcdWMyMThcdWM1ZjRcdWM1ZDAgXHVkM2VjXHVkNTY4XHViNDE4XHViMjk0IFx1YzIxOFx1YWMwMCBcdWM4ZmNcdWM1YjRcdWM5YzRcdWIyZTQuIFx1YzE0Ylx1YzlmOCBcdWM5MDRcdWM1ZDBcdWIyOTQgeFx1YWMwMCBcdWM4ZmNcdWM1YjRcdWM5YzRcdWIyZTQuICgxICZsZTsgbiAmbGU7IDEwMDAwMCwgMSAmbGU7IHggJmxlOyAyMDAwMDAwKTxcL3A+XHJcbiIsIm91dHB1dCI6IjxwPlx1YmIzOFx1YzgxY1x1Yzc1OCBcdWM4NzBcdWFjNzRcdWM3NDQgXHViOWNjXHVjODcxXHVkNTU4XHViMjk0IFx1YzMwZFx1Yzc1OCBcdWFjMWNcdWMyMThcdWI5N2MgXHVjZDljXHViODI1XHVkNTVjXHViMmU0LjxcL3A+XHJcbiIsImhpbnQiOiIiLCJvcmlnaW5hbCI6IjAiLCJodG1sX3RpdGxlIjoiMCIsInByb2JsZW1fbGFuZ190Y29kZSI6IktvcmVhbiJ9LHsicHJvYmxlbV9pZCI6IjMyNzMiLCJwcm9ibGVtX2xhbmciOiIxIiwidGl0bGUiOiJTdW1YIiwiZGVzY3JpcHRpb24iOiI8cD5Db25zaWRlciBhIHNldCBvZiBuIGRpc3RpbmN0IHBvc2l0aXZlIGludGVnZXJzIGE8c3ViPjE8XC9zdWI+LCBhPHN1Yj4yPFwvc3ViPiwgJmhlbGxpcDssIGE8c3ViPm48XC9zdWI+LCBoYXZpbmcgdmFsdWVzIGJldHdlZW4gMSBhbmQgMTAwMDAwMCBhbmQgYW4gaW50ZWdlciB4LiBXcml0ZSBhIHByb2dyYW0mbmJzcDt0byBkZXRlcm1pbmUgdGhlIG51bWJlciBvZiBwYWlycyAoYTxzdWI+aTxcL3N1Yj4sIGE8c3ViPmo8XC9zdWI+KSwgd2hlcmUgMSAmbGU7IGkgJmx0OyBqICZsZTsgbiBhbmQgYTxzdWI+aTxcL3N1Yj4gKyBhPHN1Yj5qPFwvc3ViPiA9IHguJm5ic3A7PFwvcD5cclxuIiwiaW5wdXQiOiI8cD5UaGUgZmlyc3QgbGluZSBvZiB0aGUgc3RhbmRhcmQgaW5wdXQgY29udGFpbnMgdGhlIGludGVnZXIgbiAoMSAmbGU7IG4gJmxlOyAxMDAwMDApLiBUaGUgc2Vjb25kIGxpbmUgY29udGFpbnMgbiBpbnRlZ2VycyAmbmRhc2g7IHRoZSBlbGVtZW50cyBvZiB0aGUgc2V0LiBPbiB0aGUgdGhpcmQgbGluZSB0aGUgaW50ZWdlciB4IGlzIGdpdmVuICgxICZsZTsgeCAmbGU7IDIwMDAwMDApIC4mbmJzcDs8XC9wPlxyXG4iLCJvdXRwdXQiOiI8cD5UaGUgcHJvZ3JhbSBzaG91bGQgb3V0cHV0IG9uIGEgc2luZ2xlIGxpbmUgb2YgdGhlIHN0YW5kYXJkIG91dHB1dCBhbiBpbnRlZ2VyICZuZGFzaDsgdGhlIGNhbGN1bGF0ZWQgbnVtYmVyIG9mIHBhaXJzLiZuYnNwOzxcL3A+XHJcbiIsImhpbnQiOiIiLCJvcmlnaW5hbCI6IjEiLCJodG1sX3RpdGxlIjoiMCIsInByb2JsZW1fbGFuZ190Y29kZSI6IkVuZ2xpc2gifV0=
-
자두나무
출처 : 자두나무
Solution
Python
import sys
input = sys.stdin.readline
if __name__ == '__main__':
T, W = map(int, input().split())
# [시간 흐름][W번 움직일 때 획득 자두]
DP = [[0]*(W+1) for _ in range(T+1)]
# 매시간을 입력받고, 입력받을 때마다 DP 업데이트
for t in range(1, T+1):
fallen = int(input())
# 한번도 안 움직이는 경우는 이전 값 그대로 갖고오기만 하면된다!
DP[t][0] = DP[t-1][0] + (fallen%2)
# t 시간 내 최대 이동횟수는 min(t+1, W+1)
for w in range(1, min(t+1,W+1)):
# 2번 나무 밑이라면,
if w%2==1:
# 이전에서 이동 안하거나, 이번에 이동한 값 중 큰값 + (fallen//2)
DP[t][w] = max(DP[t-1][w-1], DP[t-1][w])+(fallen//2)
# 1번 나무 밑이라면,
else:
# 이전에서 이동 안하거나, 이번에 이동한 값 중 큰값 + (fallen%2)
DP[t][w] = max(DP[t-1][w-1], DP[t-1][w])+(fallen%2)
print(max(DP[-1]))
문제
자두는 자두를 좋아한다. 그래서 집에 자두나무를 심어두고, 여기서 열리는 자두를 먹고는 한다. 하지만 자두는 키가 작아서 자두를 따먹지는 못하고, 자두가 떨어질 때까지 기다린 다음에 떨어지는 자두를 받아서 먹고는 한다. 자두를 잡을 때에는 자두가 허공에 있을 때 잡아야 하는데, 이는 자두가 말랑말랑하여 바닥에 떨어지면 못 먹을 정도로 뭉개지기 때문이다.
매 초마다, 두 개의 나무 중 하나의 나무에서 열매가 떨어지게 된다. 만약 열매가 떨어지는 순간, 자두가 그 나무의 아래에 서 있으면 자두는 그 열매를 받아먹을 수 있다. 두 개의 나무는 그다지 멀리 떨어져 있지 않기 때문에, 자두는 하나의 나무 아래에 서 있다가 다른 나무 아래로 빠르게(1초보다 훨씬 짧은 시간에) 움직일 수 있다. 하지만 자두는 체력이 그다지 좋지 못해서 많이 움직일 수는 없다.
자두는 T(1≤T≤1,000)초 동안 떨어지게 된다. 자두는 최대 W(1≤W≤30)번만 움직이고 싶어 한다. 매 초마다 어느 나무에서 자두가 떨어질지에 대한 정보가 주어졌을 때, 자두가 받을 수 있는 자두의 개수를 구해내는 프로그램을 작성하시오. 자두는 1번 자두나무 아래에 위치해 있다고 한다.
입력
첫째 줄에 두 정수 T, W가 주어진다. 다음 T개의 줄에는 각 순간에 자두가 떨어지는 나무의 번호가 1 또는 2로 주어진다.
출력
첫째 줄에 자두가 받을 수 있는 자두의 최대 개수를 출력한다.
제한
예제 입력 1
복사
7 2
2
1
1
2
2
1
1
예제 출력 1
복사
6
힌트
-
수 고르기
출처 : 수 고르기
Solution
Python
import sys
input = sys.stdin.readline
if __name__ == '__main__':
N, M = map(int, input().split())
A = [int(input()) for _ in range(N)]
A.sort() # 일단 정렬해준다.
# 초기값은 M의 최대값으로 설정
answer = 2000000000
i, j = 0, 1 # i가 더 작은 수, j는 더 큰 수 (포인터)
# j가 i보다 언제나 크니까, j가 마지막 인덱스보다 커지면 탈출
while j < N:
# 두 수의 차이 n
n = A[j]-A[i]
# M보다 클 경우,
if n >= M:
# 현재까지 차이와 n 중 더 작은 값을 고름
answer = min(answer, n)
i += 1 # 이 때는 더 작은 포인터만 움직여준다.
# 다른 경우에는 더 큰 포인터를 움직여서 두 수 차이를 늘려줘야함(M보다 커지도록)
else: j += 1
# 언제나 j는 i보다 커야하니까, 만약 같아지면 j를 +1 해준다.
if i == j: j += 1
print(answer)
# 메소드 체이닝 기법으로 한번에 연결
# from itertools import combinations
# print(min(filter(lambda x: x >= M, map(lambda x: abs(x[0]-x[1]),combinations(A, 2)))))
문제
N개의 정수로 이루어진 수열 A[1], A[2], …, A[N]이 있다. 이 수열에서 두 수를 골랐을 때(같은 수일 수도 있다), 그 차이가 M 이상이면서 제일 작은 경우를 구하는 프로그램을 작성하시오.
예를 들어 수열이 {1, 2, 3, 4, 5}라고 하자. 만약 M = 3일 경우, 1 4, 1 5, 2 5를 골랐을 때 그 차이가 M 이상이 된다. 이 중에서 차이가 가장 작은 경우는 1 4나 2 5를 골랐을 때의 3이 된다.
입력
첫째 줄에 두 정수 N, M이 주어진다. 다음 N개의 줄에는 차례로 A[1], A[2], …, A[N]이 주어진다.
출력
첫째 줄에 M 이상이면서 가장 작은 차이를 출력한다. 항상 차이가 M이상인 두 수를 고를 수 있다.
제한
1 ≤ N ≤ 100,000
0 ≤ M ≤ 2,000,000,000
0 ≤ |A[i]| ≤ 1,000,000,000
예제 입력 1
복사
3 3
1
5
3
예제 출력 1
복사
4
힌트
-
곱셈
출처 : 곱셈
Solution
Python
import sys
input = sys.stdin.readline
if __name__ == '__main__':
A, B, C = map(int, input().split())
# pow 함수가 분할정복을 통한 거듭제곱 함수이다.
# 제곱하고자하는 값, 거듭제곱 횟수, 모듈러 연산할 값
print(pow(A, B, C))
'''
# 글 참고하고 진행해보았으나, 파이썬 연산자체가 느린지 아래 방식으로 통과 안됨
# 분할정복 관련 글 : https://deepdata.tistory.com/369
answer = 1
while B:
if B&1: answer *= A
A *= A
B >> 1
if answer > 2147483647: answer %= C
print(answer)
'''
문제
자연수 A를 B번 곱한 수를 알고 싶다. 단 구하려는 수가 매우 커질 수 있으므로 이를 C로 나눈 나머지를 구하는 프로그램을 작성하시오.
입력
첫째 줄에 A, B, C가 빈 칸을 사이에 두고 순서대로 주어진다. A, B, C는 모두 2,147,483,647 이하의 자연수이다.
출력
첫째 줄에 A를 B번 곱한 수를 C로 나눈 나머지를 출력한다.
제한
예제 입력 1
복사
10 11 12
예제 출력 1
복사
4
힌트
-
감시
출처 : 감시
Solution
Python
import sys
input = sys.stdin.readline
from collections import deque
import copy
def checkVisible(board, y, x, dy, dx, N, M):
while True:
ny, nx = y+dy, x+dx
# 다음이 체크 가능한 구역이라면, 7로 설정하고 y,x값 갱신
if (0<=ny<N) & (0<=nx<M):
if board[ny][nx]!=6:
board[ny][nx] = 7
y, x = ny, nx
# 더이상 체크 불가능한 구역이라면 현재 보드를 반환
else: return board
else: return board
if __name__ == '__main__':
N, M = map(int, input().split())
CCTVS = [] # CCTV 좌표와 종류 저장
office = [] # 현재 사무실 형태 저장
for y in range(N):
# 한 줄씩 입력받기
row = list(map(int, input().split()))
# x좌표 값과 해당 타일이 뭔지 입력받고,
for x,c in enumerate(row):
# 타일이 1~5 사이의 값, 즉 CCTV면 해당 좌표와 값을 넣는다.
if c in range(1, 6): CCTVS.append((y,x,c))
# 사무실에 입력받은 열을 넣어준다.
office.append(row)
# CCTV 별로 볼 수 있는 방향을 저장 (상,하,좌,우)
one = [(1,0,0,0),(0,1,0,0),(0,0,1,0),(0,0,0,1)]
two = [(1,1,0,0),(0,0,1,1)]
three = [(1,0,0,1),(0,1,0,1),(0,1,1,0),(1,0,1,0)]
four = [(0,1,1,1),(1,0,1,1),(1,1,0,1),(1,1,1,0)]
five = [(1,1,1,1)]
# cctv 방향을 전부 저장
dirCCTV = [(), one, two, three, four, five]
answer = N*M
# CCTV가 감시가능한 구역 전부 Q에 넣는다.
Q = deque()
Q.append(office)
for cctv in CCTVS:
y,x,c = cctv # cctv의 좌표값과 종류
new = deque() # 새로운 큐를 생성
# 현재 체크해야하는 보드들
while Q:
board = Q.popleft()
# 현재 cctv가 감시 가능한 방향을 7로 바꿔주는 함수에 넣는다
for u,d,l,r in dirCCTV[c]:
# 방향 체크하는게 전부 겹치면 안되니깐, 매번 새로운 보드를 만든다.
nBoard = copy.deepcopy(board)
if u: nBoard = checkVisible(nBoard, y, x, -1, 0, N, M)
if d: nBoard = checkVisible(nBoard, y, x, 1, 0, N, M)
if l: nBoard = checkVisible(nBoard, y, x, 0, -1, N, M)
if r: nBoard = checkVisible(nBoard, y, x, 0, 1, N, M)
# new 큐에 새로 만들어진 사무실을 넣어준다.
new.append(nBoard)
# Q가 new 큐를 가르키도록 설정해준다.(이미 Q는 비어있음)
Q = new
# Q에 남은건 전부 체크완료된 사무실뿐
while Q:
office = Q.popleft()
blind = 0
# 현재 사무실에서 사각지대는 blind에 넣기
for row in office:
for tile in row:
if not tile: blind += 1
# answer과 현재 사무실 중 사각지대 더 적은걸 넣기
answer = min(answer, blind)
print(answer)
문제
스타트링크의 사무실은 1×1크기의 정사각형으로 나누어져 있는 N×M 크기의 직사각형으로 나타낼 수 있다. 사무실에는 총 K개의 CCTV가 설치되어져 있는데, CCTV는 5가지 종류가 있다. 각 CCTV가 감시할 수 있는 방법은 다음과 같다.
1번
2번
3번
4번
5번
1번 CCTV는 한 쪽 방향만 감시할 수 있다. 2번과 3번은 두 방향을 감시할 수 있는데, 2번은 감시하는 방향이 서로 반대방향이어야 하고, 3번은 직각 방향이어야 한다. 4번은 세 방향, 5번은 네 방향을 감시할 수 있다.
CCTV는 감시할 수 있는 방향에 있는 칸 전체를 감시할 수 있다. 사무실에는 벽이 있는데, CCTV는 벽을 통과할 수 없다. CCTV가 감시할 수 없는 영역은 사각지대라고 한다.
CCTV는 회전시킬 수 있는데, 회전은 항상 90도 방향으로 해야 하며, 감시하려고 하는 방향이 가로 또는 세로 방향이어야 한다.
0 0 0 0 0 0
0 0 0 0 0 0
0 0 1 0 6 0
0 0 0 0 0 0
지도에서 0은 빈 칸, 6은 벽, 1~5는 CCTV의 번호이다. 위의 예시에서 1번의 방향에 따라 감시할 수 있는 영역을 '#'로 나타내면 아래와 같다.
0 0 0 0 0 0
0 0 0 0 0 0
0 0 1 # 6 0
0 0 0 0 0 0
0 0 0 0 0 0
0 0 0 0 0 0
# # 1 0 6 0
0 0 0 0 0 0
0 0 # 0 0 0
0 0 # 0 0 0
0 0 1 0 6 0
0 0 0 0 0 0
0 0 0 0 0 0
0 0 0 0 0 0
0 0 1 0 6 0
0 0 # 0 0 0
→
←
↑
↓
CCTV는 벽을 통과할 수 없기 때문에, 1번이 → 방향을 감시하고 있을 때는 6의 오른쪽에 있는 칸을 감시할 수 없다.
0 0 0 0 0 0
0 2 0 0 0 0
0 0 0 0 6 0
0 6 0 0 2 0
0 0 0 0 0 0
0 0 0 0 0 5
위의 예시에서 감시할 수 있는 방향을 알아보면 아래와 같다.
0 0 0 0 0 #
# 2 # # # #
0 0 0 0 6 #
0 6 # # 2 #
0 0 0 0 0 #
# # # # # 5
0 0 0 0 0 #
# 2 # # # #
0 0 0 0 6 #
0 6 0 0 2 #
0 0 0 0 # #
# # # # # 5
0 # 0 0 0 #
0 2 0 0 0 #
0 # 0 0 6 #
0 6 # # 2 #
0 0 0 0 0 #
# # # # # 5
0 # 0 0 0 #
0 2 0 0 0 #
0 # 0 0 6 #
0 6 0 0 2 #
0 0 0 0 # #
# # # # # 5
왼쪽 상단 2: ↔, 오른쪽 하단 2: ↔
왼쪽 상단 2: ↔, 오른쪽 하단 2: ↕
왼쪽 상단 2: ↕, 오른쪽 하단 2: ↔
왼쪽 상단 2: ↕, 오른쪽 하단 2: ↕
CCTV는 CCTV를 통과할 수 있다. 아래 예시를 보자.
0 0 2 0 3
0 6 0 0 0
0 0 6 6 0
0 0 0 0 0
위와 같은 경우에 2의 방향이 ↕ 3의 방향이 ←와 ↓인 경우 감시받는 영역은 다음과 같다.
# # 2 # 3
0 6 # 0 #
0 0 6 6 #
0 0 0 0 #
사무실의 크기와 상태, 그리고 CCTV의 정보가 주어졌을 때, CCTV의 방향을 적절히 정해서, 사각 지대의 최소 크기를 구하는 프로그램을 작성하시오.
입력
첫째 줄에 사무실의 세로 크기 N과 가로 크기 M이 주어진다. (1 ≤ N, M ≤ 8)
둘째 줄부터 N개의 줄에는 사무실 각 칸의 정보가 주어진다. 0은 빈 칸, 6은 벽, 1~5는 CCTV를 나타내고, 문제에서 설명한 CCTV의 종류이다.
CCTV의 최대 개수는 8개를 넘지 않는다.
출력
첫째 줄에 사각 지대의 최소 크기를 출력한다.
제한
예제 입력 1
복사
4 6
0 0 0 0 0 0
0 0 0 0 0 0
0 0 1 0 6 0
0 0 0 0 0 0
예제 출력 1
복사
20
예제 입력 2
복사
6 6
0 0 0 0 0 0
0 2 0 0 0 0
0 0 0 0 6 0
0 6 0 0 2 0
0 0 0 0 0 0
0 0 0 0 0 5
예제 출력 2
복사
15
예제 입력 3
복사
6 6
1 0 0 0 0 0
0 1 0 0 0 0
0 0 1 0 0 0
0 0 0 1 0 0
0 0 0 0 1 0
0 0 0 0 0 1
예제 출력 3
복사
6
예제 입력 4
복사
6 6
1 0 0 0 0 0
0 1 0 0 0 0
0 0 1 5 0 0
0 0 5 1 0 0
0 0 0 0 1 0
0 0 0 0 0 1
예제 출력 4
복사
2
예제 입력 5
복사
1 7
0 1 2 3 4 5 6
예제 출력 5
복사
0
예제 입력 6
복사
3 7
4 0 0 0 0 0 0
0 0 0 2 0 0 0
0 0 0 0 0 0 4
예제 출력 6
복사
0
힌트
-
트리와 쿼리
출처 : 트리와 쿼리
Solution
Python
import sys
input = sys.stdin.readline
from collections import deque
if __name__ == '__main__':
# 입력받는 부분
N, R, Q = map(int, input().split())
# 연결된 간선들 저장
edges = [[] for _ in range(N+1)]
for _ in range(N-1):
U, V = map(int, input().split())
edges[U].append(V)
edges[V].append(U)
# R을 토대로 각 정점의 부모 노드를 작성해둔다.
parents = [False]*(N+1)
parents[R] = True # 루트 노드는 True을 넣어둔다.
# 각 노드들의 깊이를 저장할 배열
depth = [False]*(N+1)
depth[R] = 0 # 루트 노드는 0을 넣어둔다.
# BFS 형식으로 부모 노드 찾아두기
queue = deque()
queue.append(R)
while queue:
# 트리의 각 깊이에 해당하는 노드들이 들어오고 체크하게 될 예정
n = queue.popleft()
d = depth[n]+1 # n의 자녀노드를 체크할거니까 깊이는 +1
# 현재 노드와 연결된 정점들 중
for v in edges[n]:
# 아직 부모 노드가 연결되지 않은 정점은
if not parents[v]:
parents[v] = n # n을 부모노드로 설정해주고,
queue.append(v) # 다음 탐색을 위해 큐에 넣어준다.
depth[v] = d # 자녀 노드의 깊이를 작성해준다.
# 각 노드의 서브트리 정점의 수를 저장할 배열
numSub = [1]*(N+1)
# 깊이, 부모, 해당정점 넘버를 깊이순으로 탐색하며 numSub에 저장해주자
# 첫번째 0 인덱스는 제외해주고, sorted 하면 루트노드가 마지막에 오므로 루트노드의 p는 없으니 제외해준다.
for d,p,i in sorted(tuple(zip(depth, parents, range(N+1)))[1:], reverse=True)[:-1]:
numSub[p] += numSub[i]
# 쿼리를 입력받을 때마다, 바로바로 연산 후 결과 출력한다.
for _ in range(Q):
q = int(input())
print(numSub[q])
문제
간선에 가중치와 방향성이 없는 임의의 루트 있는 트리가 주어졌을 때, 아래의 쿼리에 답해보도록 하자.
정점 U를 루트로 하는 서브트리에 속한 정점의 수를 출력한다.
만약 이 문제를 해결하는 데에 어려움이 있다면, 하단의 힌트에 첨부한 문서를 참고하자.
입력
트리의 정점의 수 N과 루트의 번호 R, 쿼리의 수 Q가 주어진다. (2 ≤ N ≤ 105, 1 ≤ R ≤ N, 1 ≤ Q ≤ 105)
이어 N-1줄에 걸쳐, U V의 형태로 트리에 속한 간선의 정보가 주어진다. (1 ≤ U, V ≤ N, U ≠ V)
이는 U와 V를 양 끝점으로 하는 간선이 트리에 속함을 의미한다.
이어 Q줄에 걸쳐, 문제에 설명한 U가 하나씩 주어진다. (1 ≤ U ≤ N)
입력으로 주어지는 트리는 항상 올바른 트리임이 보장된다.
출력
Q줄에 걸쳐 각 쿼리의 답을 정수 하나로 출력한다.
제한
예제 입력 1
복사
9 5 3
1 3
4 3
5 4
5 6
6 7
2 3
9 6
6 8
5
4
8
예제 출력 1
복사
9
4
1
힌트
그래프란, 정점들과 정점 둘을 잇는 간선들로 이루어진 집합을 의미한다.
위는 9개의 정점(원 모양)과, 10개의 간선(실선) 들로 이루어진 그래프이다. 각 원의 내부에 쓰여 있는 숫자는 편의상 정점에 매긴 번호를 의미한다.
붉은 간선은 차후 설명의 편의상 색칠해 둔 것으로, 우선은 다른 검은 간선과 동일한 것으로 간주하도록 하자.
간선은 항상 두 정점을 잇게 된다. 이제부터의 설명에서는, 각 정점을 번호로(1번 정점, 2번 정점.. ), 간선을 양 끝점의 정점의 번호로(1-3, 3-2… ) 표기하도록 하자.
그래프의 간선에는 가중치가 있을 수도 있다. 만일 특별한 언급이 없다면 모든 간선의 가중치가 1인 그래프로 간주할 수 있으며, 가중치가 존재한다면, 예를 들어 1-3 간선의 가중치가 3이라면, 1번 정점에서 3번 정점으로 가기 위해선 길이 3인 간선을 지나야 한다고 표현한다. 위의 그래프는 모든 간선의 길이가 1인 예시라고 보면 된다.
그래프의 간선에는 방향성이 있을 수도 있다. 예를 들어, 1번과 3번 정점 사이에 놓인 1-3 간선의 경우, 1->3 또는 3->1의 방향성을 가지는 것이 가능하다. 방향성 간선을 갖고 있는 그래프를 ‘유향 그래프’, 위의 그림처럼 방향성이 없는 간선만으로 이루어진 그래프를 ‘무향 그래프’ 라 한다. 간선의 방향성은 그래프에서 탐색을 진행할 때 결과를 달리할 수 있다. 예를 들어, 현재 위의 그래프에서 1번 정점에서 4번 정점까지 가면서, 간선을 최소한 거치는 경로는 1->3->4로, 총 2개의 간선을 거친다. 우리는 이것을 ‘1번 정점과 4번 정점의 최단 경로는 2다’ 라고 표현한다. 하지만 만약 3번 정점과 4번 정점 사이의 간선이 4->3의 방향성을 가진다면, 1번 정점에서 4번 정점으로 가는 최단 경로는 1->3->6->5->4 로, 총 4개의 간선을 지나야 한다. 즉, 최단 경로가 4가 된다.
그래프에서는 ‘사이클’ 을 정의할 수 있다. 무향 그래프에서의 사이클이란, 어떤 정점에서 출발해 시작점을 제외한 어떤 정점도, 어떤 간선도 두 번 이상 방문하지 않고 시작점으로 돌아올 수 있는 경로를 의미한다. 예를 들어, 위의 그림에서는 3-6-5-4-3 사이클과, 6-7-9 사이클이 존재한다. 1-3-1은 1-3 간선을 두 번 지났으므로 사이클이 될 수 없으며, 1-3-6-5-4-3은 시작점으로 돌아오지 않는 경로이므로 사이클이 아니다.
만일 그래프에 단 하나의 사이클도 없다면, 해당 그래프는 ‘트리’ 라고 부른다. 이는 그래프가 마치 하나의 정점에서 출발해 피어난 나무 모양과도 같음에 붙여진 이름으로, 예를 들어 위의 그림에서 빨간 간선 두 개를 제거한다면 위의 그래프는 트리가 된다. 예를 들어, 상단에 주어진 그래프에서 빨간 간선 두 개를 제거한 뒤 만들어진 트리의 모습은 아래와 같다.
일반적으로 그래프에서는 정점의 위치나 간선의 모양 등에 대한 조건은 전혀 고려하지 않으며, 오직 연결성만을 고려하므로, 간선의 집합이 변하지 않는다는 가정 하에 그래프를 얼마든지 다시 그릴 수가 있다. 위의 트리에서 5번 정점을 잡고 위로 들어올리는 예시를 생각해 보자. 아래쪽에 중력이 작용한다고 생각하고 5번 정점을 위쪽으로 들어올리게 되면 트리의 모양은 아래와 같이 변할 것이다.
간선의 집합에 변함이 없는 한, 그래프는 얼마든지 원하는 대로 다시 그릴 수가 있다. 예를 들어, 위의 트리를 거울에 비추어 좌우를 바꿀 경우에도 동일한 트리가 된다.
트리에는 루트(root)가 있을 수도 없을 수도 있지만, 편의를 위해서라면 아무 정점이나 루트로 선택할 수 있다. 5번 정점을 루트로 하였다고 생각한 뒤 위의 트리를 다시 보도록 하자.
트리는 항상 루트를 기준으로 다시 그릴 수 있기 때문에, 루트가 고정되지 않는 한 어떤 정점이 ‘위에’ 있는지 판정할 수는 없다. 하지만 루트가 고정된다면, 우리는 정점 간에 ‘부모’ 와 ‘자식’ 의 관계를 정의할 수가 있다. 예를 들어, 위의 트리에서는 4번 정점의 부모는 5번 정점이며, 3번 정점은 4번 정점의 자식이 된다. 5번 정점의 부모는 없으며, 4, 6번 정점을 두 자식으로 갖게 될 것이다.
트리에는 몇 가지 중요한 성질이 있는데, 그 중 두 가지만 추려보자면 아래와 같다.
임의의 두 정점 U와 V에 대해, U에서 V로 가는 최단경로는 유일하다.
아무 정점이나 잡고 부모와의 연결을 끊었을 때, 해당 정점과 그 자식들, 그 자식들의 자식들… 로 이루어진 부분그래프는 트리가 된다.
둘 모두 직관적이며 자명한 사실이므로 증명은 생략한다. 두 번째 성질에서, 끊어진 부분그래프로 만들어진 트리를 ‘서브트리’ 라고 부른다.
만약 트리에 대한 문제 하나가 출제되었다고 가정해보자. 입력이 위처럼 루트와 그 자식들로 이루어진다면 좋지만, 루트가 없는 일반 트리의 형태(두 번째 그림)의 형태로 입력이 주어질 수도 있다. 예를 들어, 정점의 개수와 간선의 목록만이 주어진다면, 어떻게 트리를 구성할 수 있을까?
예를 들어, 위의 트리에 대해 정점의 개수와 간선의 목록이 아래와 같이 입력된다고 하자.
9
1 3
4 3
5 4
5 6
6 7
2 3
9 6
6 8
첫 줄의 9는 정점의 개수이며, 나머지 8쌍의 두 정수는 간선의 양 끝점 번호를 의미한다. 트리에서의 간선의 개수는 항상 정점의 수 - 1이라는 것은 익히 알려진 사실이며, 증명 또한 어렵지 않으므로 설명을 생략한다.
위와 같은 데이터를 트리로 구성하기 위해서는, 우선 루트 하나를 임의로 정의하는 것이 편하다. 5번 정점을 루트로 정해보도록 하자.
트리에는 부모와 자식 관계가 있으므로, 각 정점별로 부모가 누구인지, 자식들의 목록은 어떻게 되는지를 저장해 두면 요긴하게 쓰일 것이다. 이를 아래와 같이 구현할 수 있다.
def makeTree(currentNode, parent) :
for(Node in connect[currentNode]) :
if Node != parent:
add Node to currentNode’s child
set Node’s parent to currentNode
makeTree(Node, currentNode)
currentNode는 현재 탐색 중인 정점이며, parent는 해당 정점의 부모 정점이다.
트리에서는 (눈치챘을 수도 있지만) 어떤 정점의 부모는 하나이거나 없다. 따라서, 어떤 정점에 대해 연결된 모든 정점은 최대 한 개의 정점을 제외하면 모두 해당 정점의 자식들이 될 것이다. 이에 따라, 부모 정점의 정보를 가져가면서, 부모 정점이 아니면서 자신과 연결되어 있는 모든 정점을 자신의 자식으로, 자신의 자식이 될 정점들의 부모 정점을 자신으로 연결한 뒤 재귀적으로 자식 정점들에게 트리 구성을 요청하는 형태의 함수이다.
위와 같이 정의한 뒤엔, 메인 함수에서 한 차례 makeTree(5, -1) 을 호출할 경우 5번 정점을 루트로 하는 트리를 구성할 수 있다. -1은 부모가 없음을 의미한다.
그렇다면, 일반적인 형태의 트리에서 루트가 주어진 뒤 여러 질의가 주어지는 상황을 생각해 보자. 예를 들어, 5번 정점을 루트로 하는 트리에 대해, ‘정점 U를 루트로 하는 서브트리의 정점의 수는 얼마인가?’ 라는 질의가 다수 주어진다고 해 보자. U를 루트로 하는 서브트리란, 위에도 언급하였지만 정점 U와 그 부모의 연결을 끊고 정점 U를 기준으로 그 자식들, 자식들의 자식들… 로 만든 트리를 말한다. 예를 들어, 5번 정점이 루트일 때 4번 정점을 루트로 하는 서브트리에서의 정점의 수는 4개이며, 8번 정점을 루트로 하는 서브트리에서의 정점의 수는 1개가 된다.
물론 직접 연결을 끊은 뒤 다시 정점의 수를 세는 방법도 가능하겠지만, 트리의 정점 수가 많고, 질의 또한 많다면 프로그램이 제한시간 내에 수행될 수 없을 확률이 높다. 아마 미리 모든 정점을 각각 루트로 하는 서브트리에서의 정점의 수를 빠르게 구해 둘 방법이 있다면 좋을 것이다.
이를 구현하기 위해, 트리를 구성하던 코드의 동작 과정을 살펴보도록 하자. 루트에서 출발하여, 자식 정점들에 대해 한 번씩 트리 구성을 요청하게 된다. 여기에서 알 수 있는 사실은, 자식 정점들에 대한 makeTree가 호출된 뒤엔, 해당 자식 정점을 서브트리로 하는 트리가 구성이 완료된다는 것이다. 이와 같은 원리로 모든 정점에 대해 해당 정점을 루트로 하는 서브트리에 속한 정점의 수를 계산하는 함수를 만들어보도록 하자.
def countSubtreeNodes(currentNode) :
size[currentNode] = 1 // 자신도 자신을 루트로 하는 서브트리에 포함되므로 0이 아닌 1에서 시작한다.
for Node in currentNode’s child:
countSubtreeNode(Node)
size[currentNode] += size[Node]
자식 정점들에 대해 모두 서브트리에 속한 정점의 수를 계산하게 만든 뒤 각각의 정점 수를 더해 자신을 루트로 하는 서브트리에 속한 정점의 수를 만들게 된다. 이제 메인 함수 내에서 makeTree(5, -1)과 countSubtreeNodes(5) 를 차례대로 한 번씩 호출할 경우, 5번을 루트로 하는 트리에서 모든 정점에 대해 각 정점을 루트로 하는 서브트리에 속한 정점의 수를 계산해둘 수가 있다. 이를 이용하면, 모든 질의 U에 대해 size[U] 를 출력하기만 하면 되므로, 정점이 10만 개, 질의가 10만 개인 데이터에서도 충분히 빠른 시간 내에 모든 질의를 처리할 수가 있게 될 것이다.
-
시리얼 번호
출처 : 시리얼 번호
Solution
Python
import sys
input = sys.stdin.readline
if __name__ == '__main__':
N = int(input())
SN = []
# 1번조건(길이)과 2번조건(숫자합)을 한번에 연산하기 위해 따로 입력받음
for _ in range(N):
sn = input().strip()
# 시리얼번호 중 숫자는 전부 더해서 s에 저장한다.
s = sum(int(c) for c in sn if c.isdigit())
# 길이, 숫자합, 시리얼번호 순으로 SN에 저장.
SN.append((len(sn), s, sn))
# 그냥 sort 해주면 첫번째 인덱스부터 차례대로 비교해준다.
SN.sort()
# 출력은 마지막 원소인 시리얼번호만 해준다.
for sn in SN: print(sn[2])
문제
다솜이는 기타를 많이 가지고 있다. 그리고 각각의 기타는 모두 다른 시리얼 번호를 가지고 있다. 다솜이는 기타를 빨리 찾아서 빨리 사람들에게 연주해주기 위해서 기타를 시리얼 번호 순서대로 정렬하고자 한다.
모든 시리얼 번호는 알파벳 대문자 (A-Z)와 숫자 (0-9)로 이루어져 있다.
시리얼번호 A가 시리얼번호 B의 앞에 오는 경우는 다음과 같다.
A와 B의 길이가 다르면, 짧은 것이 먼저 온다.
만약 서로 길이가 같다면, A의 모든 자리수의 합과 B의 모든 자리수의 합을 비교해서 작은 합을 가지는 것이 먼저온다. (숫자인 것만 더한다)
만약 1,2번 둘 조건으로도 비교할 수 없으면, 사전순으로 비교한다. 숫자가 알파벳보다 사전순으로 작다.
시리얼이 주어졌을 때, 정렬해서 출력하는 프로그램을 작성하시오.
입력
첫째 줄에 기타의 개수 N이 주어진다. N은 50보다 작거나 같다. 둘째 줄부터 N개의 줄에 시리얼 번호가 하나씩 주어진다. 시리얼 번호의 길이는 최대 50이고, 알파벳 대문자 또는 숫자로만 이루어져 있다. 시리얼 번호는 중복되지 않는다.
출력
첫째 줄부터 차례대로 N개의 줄에 한줄에 하나씩 시리얼 번호를 정렬한 결과를 출력한다.
제한
예제 입력 1
복사
5
ABCD
145C
A
A910
Z321
예제 출력 1
복사
A
ABCD
Z321
145C
A910
예제 입력 2
복사
2
Z19
Z20
예제 출력 2
복사
Z20
Z19
예제 입력 3
복사
4
34H2BJS6N
PIM12MD7RCOLWW09
PYF1J14TF
FIPJOTEA5
예제 출력 3
복사
FIPJOTEA5
PYF1J14TF
34H2BJS6N
PIM12MD7RCOLWW09
예제 입력 4
복사
5
ABCDE
BCDEF
ABCDA
BAAAA
ACAAA
예제 출력 4
복사
ABCDA
ABCDE
ACAAA
BAAAA
BCDEF
힌트
-
연결 요소의 개수
출처 : 연결 요소의 개수
Solution
Python
import sys
input = sys.stdin.readline
from collections import deque
def find_CC(graph, N):
# 탐색완료한 정점 체크용 배열
visited = [False]*N
result = 0 # 찾은 연결 요소 수
for i in range(N):
# 만약 i가 체크 안된 정점이라면,
if not visited[i]:
# bfs 로 탐색하자
Q = deque()
# 체크 안된 정점을 Q에 넣고 방문 체크
Q.append(i)
visited[i] = True
while Q:
node = Q.popleft()
# 연결되어 있는 정점을 전부 체크
for v in graph[node]:
# 방문 안 한 곳이라면 Q에 추가 후 방문 체크
if not visited[v]:
Q.append(v)
visited[v] = True
# 일련의 과정이 끝나면 연결 요소 1개 찾은 것
result += 1
return result
if __name__ == '__main__':
N, M = map(int, input().split())
# 만들어지는 그래프를 인접 리스트 형태로 저장
graph = [[] for _ in range(N)]
for _ in range(M):
# 입력받는 간선을 0 넘버링으로 바꿔준다.
u, v = map(lambda x: int(x)-1, input().split())
graph[u].append(v)
graph[v].append(u)
# 연결 요소 찾는 함수로 값을 찾아준다.
print(find_CC(graph, N))
문제
방향 없는 그래프가 주어졌을 때, 연결 요소 (Connected Component)의 개수를 구하는 프로그램을 작성하시오.
입력
첫째 줄에 정점의 개수 N과 간선의 개수 M이 주어진다. (1 ≤ N ≤ 1,000, 0 ≤ M ≤ N×(N-1)/2) 둘째 줄부터 M개의 줄에 간선의 양 끝점 u와 v가 주어진다. (1 ≤ u, v ≤ N, u ≠ v) 같은 간선은 한 번만 주어진다.
출력
첫째 줄에 연결 요소의 개수를 출력한다.
제한
예제 입력 1
복사
6 5
1 2
2 5
5 1
3 4
4 6
예제 출력 1
복사
2
예제 입력 2
복사
6 8
1 2
2 5
5 1
3 4
4 6
5 4
2 4
2 3
예제 출력 2
복사
1
힌트
-
요세푸스 문제
출처 : 요세푸스 문제
Solution
Python
import sys
input = sys.stdin.readline
from collections import deque
if __name__ == '__main__':
N, K = map(int, input().split())
K -= 1 # K-1 만큼 회전시켜야 K번째 숫자를 꺼냄
Q = deque(range(1, N+1)) # 1~N까지를 Q에 넣는다!
# 출력 시작은 <
print('<', end='')
# Q가 끝날 때까지 반복문 시작
while Q:
# K-1만큼 왼쪽으로 돌려야하니 rotate(-K)
Q.rotate(-K)
# 현재 왼쪽 첫번째 원소가 K번째 사람(숫자)
print(Q.popleft(), end='')
# 만약 Q에 값이 아직 남아있다면 ', ' 넣어주기
if len(Q): print(', ', end='')
# 마무리
print('>')
문제
요세푸스 문제는 다음과 같다.
1번부터 N번까지 N명의 사람이 원을 이루면서 앉아있고, 양의 정수 K(≤ N)가 주어진다. 이제 순서대로 K번째 사람을 제거한다. 한 사람이 제거되면 남은 사람들로 이루어진 원을 따라 이 과정을 계속해 나간다. 이 과정은 N명의 사람이 모두 제거될 때까지 계속된다. 원에서 사람들이 제거되는 순서를 (N, K)-요세푸스 순열이라고 한다. 예를 들어 (7, 3)-요세푸스 순열은 <3, 6, 2, 7, 5, 1, 4>이다.
N과 K가 주어지면 (N, K)-요세푸스 순열을 구하는 프로그램을 작성하시오.
입력
첫째 줄에 N과 K가 빈 칸을 사이에 두고 순서대로 주어진다. (1 ≤ K ≤ N ≤ 5,000)
출력
예제와 같이 요세푸스 순열을 출력한다.
제한
예제 입력 1
복사
7 3
예제 출력 1
복사
<3, 6, 2, 7, 5, 1, 4>
힌트
-
회사에 있는 사람
출처 : 회사에 있는 사람
Solution
Python
import sys
input = sys.stdin.readline
if __name__ == '__main__':
N = int(input())
# 현재 회사에 남아있는 사람
now = set() # 리스트로 입력받으면 시간 초과됨!
for _ in range(N):
name, order = input().rstrip().split()
# 출퇴근(order)에 따라서 나뉘게 match로 구현
match order:
case "enter":
now.add(name)
case "leave":
now.remove(name)
# 배열을 반환해주도록, sorted를 사용, 역순정렬
answer = sorted(list(now), reverse=True)
print(*answer)
문제
상근이는 세계적인 소프트웨어 회사 기글에서 일한다. 이 회사의 가장 큰 특징은 자유로운 출퇴근 시간이다. 따라서, 직원들은 반드시 9시부터 6시까지 회사에 있지 않아도 된다.
각 직원은 자기가 원할 때 출근할 수 있고, 아무때나 퇴근할 수 있다.
상근이는 모든 사람의 출입카드 시스템의 로그를 가지고 있다. 이 로그는 어떤 사람이 회사에 들어왔는지, 나갔는지가 기록되어져 있다. 로그가 주어졌을 때, 현재 회사에 있는 모든 사람을 구하는 프로그램을 작성하시오.
입력
첫째 줄에 로그에 기록된 출입 기록의 수 n이 주어진다. (2 ≤ n ≤ 106) 다음 n개의 줄에는 출입 기록이 순서대로 주어지며, 각 사람의 이름이 주어지고 "enter"나 "leave"가 주어진다. "enter"인 경우는 출근, "leave"인 경우는 퇴근이다.
회사에는 동명이인이 없으며, 대소문자가 다른 경우에는 다른 이름이다. 사람들의 이름은 알파벳 대소문자로 구성된 5글자 이하의 문자열이다.
출력
현재 회사에 있는 사람의 이름을 사전 순의 역순으로 한 줄에 한 명씩 출력한다.
제한
예제 입력 1
복사
4
Baha enter
Askar enter
Baha leave
Artem enter
예제 출력 1
복사
Askar
Artem
힌트
W3sicHJvYmxlbV9pZCI6Ijc3ODUiLCJwcm9ibGVtX2xhbmciOiIwIiwidGl0bGUiOiJcdWQ2OGNcdWMwYWNcdWM1ZDAgXHVjNzg4XHViMjk0IFx1YzBhY1x1Yjc4YyIsImRlc2NyaXB0aW9uIjoiPHA+XHVjMGMxXHVhZGZjXHVjNzc0XHViMjk0IFx1YzEzOFx1YWNjNFx1YzgwMVx1Yzc3OCBcdWMxOGNcdWQ1MDRcdWQyYjhcdWM2ZThcdWM1YjQgXHVkNjhjXHVjMGFjIFx1YWUzMFx1YWUwMFx1YzVkMFx1YzExYyBcdWM3N2NcdWQ1NWNcdWIyZTQuIFx1Yzc3NCBcdWQ2OGNcdWMwYWNcdWM3NTggXHVhYzAwXHVjN2E1IFx1ZDA3MCBcdWQyYjlcdWM5ZDVcdWM3NDAgXHVjNzkwXHVjNzIwXHViODVjXHVjNmI0IFx1Y2Q5Y1x1ZDFmNFx1YWRmYyBcdWMyZGNcdWFjMDRcdWM3NzRcdWIyZTQuIFx1YjUzMFx1Yjc3Y1x1YzExYywgXHVjOWMxXHVjNmQwXHViNGU0XHVjNzQwIFx1YmMxOFx1YjRkY1x1YzJkYyZuYnNwOzlcdWMyZGNcdWJkODBcdWQxMzAgNlx1YzJkY1x1YWU0Y1x1YzljMCBcdWQ2OGNcdWMwYWNcdWM1ZDAgXHVjNzg4XHVjOWMwIFx1YzU0YVx1YzU0NFx1YjNjNCBcdWI0MWNcdWIyZTQuPFwvcD5cclxuXHJcbjxwPlx1YWMwMSBcdWM5YzFcdWM2ZDBcdWM3NDAgXHVjNzkwXHVhZTMwXHVhYzAwIFx1YzZkMFx1ZDU2MCBcdWI1NGMgXHVjZDljXHVhZGZjXHVkNTYwIFx1YzIxOCBcdWM3ODhcdWFjZTAsIFx1YzU0NFx1YmIzNFx1YjU0Y1x1YjA5OCBcdWQxZjRcdWFkZmNcdWQ1NjAgXHVjMjE4IFx1Yzc4OFx1YjJlNC48XC9wPlxyXG5cclxuPHA+XHVjMGMxXHVhZGZjXHVjNzc0XHViMjk0IFx1YmFhOFx1YjRlMCBcdWMwYWNcdWI3OGNcdWM3NTggXHVjZDljXHVjNzg1XHVjZTc0XHViNGRjIFx1YzJkY1x1YzJhNFx1ZDE1Y1x1Yzc1OCBcdWI4NWNcdWFkZjhcdWI5N2MgXHVhYzAwXHVjOWMwXHVhY2UwIFx1Yzc4OFx1YjJlNC4gXHVjNzc0IFx1Yjg1Y1x1YWRmOFx1YjI5NCBcdWM1YjRcdWI1YTQgXHVjMGFjXHViNzhjXHVjNzc0IFx1ZDY4Y1x1YzBhY1x1YzVkMCBcdWI0ZTRcdWM1YjRcdWM2NTRcdWIyOTRcdWM5YzAsIFx1YjA5OFx1YWMxNFx1YjI5NFx1YzljMFx1YWMwMCBcdWFlMzBcdWI4NWRcdWI0MThcdWM1YjRcdWM4MzggXHVjNzg4XHViMmU0LiBcdWI4NWNcdWFkZjhcdWFjMDAgXHVjOGZjXHVjNWI0XHVjODRjXHVjNzQ0IFx1YjU0YywgXHVkNjA0XHVjN2FjIFx1ZDY4Y1x1YzBhY1x1YzVkMCBcdWM3ODhcdWIyOTQgXHViYWE4XHViNGUwIFx1YzBhY1x1Yjc4Y1x1Yzc0NCBcdWFkNmNcdWQ1NThcdWIyOTQgXHVkNTA0XHViODVjXHVhZGY4XHViN2E4XHVjNzQ0IFx1Yzc5MVx1YzEzMVx1ZDU1OFx1YzJkY1x1YzYyNC48XC9wPlxyXG4iLCJpbnB1dCI6IjxwPlx1Y2NhYlx1YzlmOCBcdWM5MDRcdWM1ZDAgXHViODVjXHVhZGY4XHVjNWQwIFx1YWUzMFx1Yjg1ZFx1YjQxYyBcdWNkOWNcdWM3ODUgXHVhZTMwXHViODVkXHVjNzU4IFx1YzIxOCBuXHVjNzc0IFx1YzhmY1x1YzViNFx1YzljNFx1YjJlNC4gKDIgJmxlOyBuICZsZTsgMTA8c3VwPjY8XC9zdXA+KSBcdWIyZTRcdWM3NGMgblx1YWMxY1x1Yzc1OCBcdWM5MDRcdWM1ZDBcdWIyOTQgXHVjZDljXHVjNzg1IFx1YWUzMFx1Yjg1ZFx1Yzc3NCBcdWMyMWNcdWMxMWNcdWIzMDBcdWI4NWMgXHVjOGZjXHVjNWI0XHVjOWMwXHViYTcwLCBcdWFjMDEgXHVjMGFjXHViNzhjXHVjNzU4IFx1Yzc3NFx1Yjk4NFx1Yzc3NCBcdWM4ZmNcdWM1YjRcdWM5YzBcdWFjZTAgJnF1b3Q7ZW50ZXImcXVvdDtcdWIwOTggJnF1b3Q7bGVhdmUmcXVvdDtcdWFjMDAgXHVjOGZjXHVjNWI0XHVjOWM0XHViMmU0LiAmcXVvdDtlbnRlciZxdW90O1x1Yzc3OCBcdWFjYmRcdWM2YjBcdWIyOTQgXHVjZDljXHVhZGZjLCAmcXVvdDtsZWF2ZSZxdW90O1x1Yzc3OCBcdWFjYmRcdWM2YjBcdWIyOTQgXHVkMWY0XHVhZGZjXHVjNzc0XHViMmU0LjxcL3A+XHJcblxyXG48cD5cdWQ2OGNcdWMwYWNcdWM1ZDBcdWIyOTQgXHViM2Q5XHViYTg1XHVjNzc0XHVjNzc4XHVjNzc0IFx1YzVjNlx1YzczY1x1YmE3MCwgXHViMzAwXHVjMThjXHViYjM4XHVjNzkwXHVhYzAwIFx1YjJlNFx1Yjk3OCBcdWFjYmRcdWM2YjBcdWM1ZDBcdWIyOTQgXHViMmU0XHViOTc4IFx1Yzc3NFx1Yjk4NFx1Yzc3NFx1YjJlNC4mbmJzcDtcdWMwYWNcdWI3OGNcdWI0ZTRcdWM3NTggXHVjNzc0XHViOTg0XHVjNzQwIFx1YzU0Y1x1ZDMwY1x1YmNiMyBcdWIzMDBcdWMxOGNcdWJiMzhcdWM3OTBcdWI4NWMgXHVhZDZjXHVjMTMxXHViNDFjIDVcdWFlMDBcdWM3OTAgXHVjNzc0XHVkNTU4XHVjNzU4IFx1YmIzOFx1Yzc5MFx1YzVmNFx1Yzc3NFx1YjJlNC48XC9wPlxyXG4iLCJvdXRwdXQiOiI8cD5cdWQ2MDRcdWM3YWMgXHVkNjhjXHVjMGFjXHVjNWQwIFx1Yzc4OFx1YjI5NCBcdWMwYWNcdWI3OGNcdWM3NTggXHVjNzc0XHViOTg0XHVjNzQ0IFx1YzBhY1x1YzgwNCBcdWMyMWNcdWM3NTggXHVjNWVkXHVjMjFjXHVjNzNjXHViODVjIFx1ZDU1YyBcdWM5MDRcdWM1ZDAgXHVkNTVjIFx1YmE4NVx1YzUyOSBcdWNkOWNcdWI4MjVcdWQ1NWNcdWIyZTQuPFwvcD5cclxuIiwiaGludCI6IiIsIm9yaWdpbmFsIjoiMCIsImh0bWxfdGl0bGUiOiIwIiwicHJvYmxlbV9sYW5nX3Rjb2RlIjoiS29yZWFuIn0seyJwcm9ibGVtX2lkIjoiNzc4NSIsInByb2JsZW1fbGFuZyI6IjEiLCJ0aXRsZSI6IkVhc3kgd29yayIsImRlc2NyaXB0aW9uIjoiPHA+WW91IGFyZSB3b3JraW5nIGluIGEgJnJkcXVvO0dpaWdsZSZyZHF1bzsgc29mdHdhcmUgY29tcGFueS4gVGhlIGpvYiBpbiB0aGlzIGNvbXBhbnkgaXMgdmVyeSBlYXN5LCBzbyBwZW9wbGUgZG9uJnJzcXVvO3Qgc2l0IGluIHRoZSBvXHVmYjAzY2UgZnJvbSA5YW0gdGlsbCA2cG0uIFRoZXkgY29tZSB0byB3b3JrIGF0IGFueSB0aW1lLCBhbmQgbGVhdmUgdGhlIG9cdWZiMDNjZSBhdCBhbnkgdGltZS4gWW91IGhhdmUgYSBtYWduZXRpYyBrZXlzIHN5c3RlbSB0aGF0IGtlZXBzIHRoZSBsb2cgb24gYWxsIHBlb3BsZSAmbmRhc2g7IHdoZW4gdGhleSBlbnRlcmVkIHRoZSBvXHVmYjAzY2UsIGFuZCB3aGVuIHRoZXkgbGVhdmVkLiBZb3VyIHRhc2sgaXMgdG8gXHVmYjAxbmQgYWxsIHBlb3BsZSB0aGF0IGFyZSBpbiBvXHVmYjAzY2Ugbm93LjxcL3A+XHJcbiIsImlucHV0IjoiPHA+VGhlIFx1ZmIwMXJzdCBsaW5lIG9mIHRoZSBpbnB1dCBcdWZiMDFsZSBjb250YWlucyBuICZtZGFzaDsgdGhlIG51bWJlciBvZiBsaW5lcyBpbiBpbnB1dCBcdWZiMDFsZSAoMiAmbGU7IG4gJmxlOyAxMDxzdXA+NjxcL3N1cD4pLiBFYWNoIG9mIHRoZSBmb2xsb3dpbmcgbiBsaW5lcyBjb250YWluIHBlcnNvbiBuYW1lIGFuZCB3b3JkICZyZHF1bztlbnRlciZyZHF1bzsgaWYgdGhpcyBwZXJzb24gaXMgZW50ZXJlZCwgYW5kICZyZHF1bztsZWF2ZSZyZHF1bzsgb3RoZXJ3aXNlLjxcL3A+XHJcbiIsIm91dHB1dCI6IjxwPk91dHB1dCBuYW1lcyBvZiBhbGwgcGVvcGxlIHRoYXQgYXJlIGluIG9cdWZiMDNjZSBub3cgaW4gYW50aS1sZXhpY29ncmFwaGljYWwgb3JkZXIuPFwvcD5cclxuXHJcbjxwPiZuYnNwOzxcL3A+XHJcbiIsImhpbnQiOiIiLCJvcmlnaW5hbCI6IjEiLCJodG1sX3RpdGxlIjoiMCIsInByb2JsZW1fbGFuZ190Y29kZSI6IkVuZ2xpc2gifV0=
-
-
절댓값 힙
출처 : 절댓값 힙
Solution
Python
import sys
input = sys.stdin.readline
# 일단 우선순위 큐로 구현
import heapq
if __name__ == '__main__':
N = int(input())
# 우선순위 큐로 쓰기 위한 리스트
heap = []
# N 번 반복하기 위해 for문으로 구현
for _ in range(N):
# N 번 입력받는다.
x = int(input())
# 0 이 아니라면 우선순위 큐 에 원소를 넣는 연산
if x!=0:
# 절댓값 기준 정렬이 되면서 출력값은 입력값이어야해서 튜플 통해서 입력
# 공식문서 참고 시, heapq에는 튜플이 가능하며, 0 인덱스 값 기준으로 정렬됨을 알 수 있다.
heapq.heappush(heap, (abs(x), x))
else:
# 만약 입력값이 0이라면,
try:
# heapq 에서 가장 절댓값이 작은 값을 뽑아내고, 튜플형태이기에 1 인덱스의 원본 값을 print 한다.
print(heapq.heappop(heap)[1])
# heapq 에 원소가 없다면 에러가 발생 (out of index)
except:
print(0)
문제
절댓값 힙은 다음과 같은 연산을 지원하는 자료구조이다.
배열에 정수 x (x ≠ 0)를 넣는다.
배열에서 절댓값이 가장 작은 값을 출력하고, 그 값을 배열에서 제거한다. 절댓값이 가장 작은 값이 여러개일 때는, 가장 작은 수를 출력하고, 그 값을 배열에서 제거한다.
프로그램은 처음에 비어있는 배열에서 시작하게 된다.
입력
첫째 줄에 연산의 개수 N(1≤N≤100,000)이 주어진다. 다음 N개의 줄에는 연산에 대한 정보를 나타내는 정수 x가 주어진다. 만약 x가 0이 아니라면 배열에 x라는 값을 넣는(추가하는) 연산이고, x가 0이라면 배열에서 절댓값이 가장 작은 값을 출력하고 그 값을 배열에서 제거하는 경우이다. 입력되는 정수는 -231보다 크고, 231보다 작다.
출력
입력에서 0이 주어진 회수만큼 답을 출력한다. 만약 배열이 비어 있는 경우인데 절댓값이 가장 작은 값을 출력하라고 한 경우에는 0을 출력하면 된다.
제한
예제 입력 1
복사
18
1
-1
0
0
0
1
1
-1
-1
2
-2
0
0
0
0
0
0
0
예제 출력 1
복사
-1
1
0
-1
-1
1
1
-2
2
0
힌트
-
스택
출처 : 스택
Solution
Python
import sys
input = sys.stdin.readline
# 큐나 스택 구현에는 deque가 최고
from collections import deque
if __name__ == '__main__':
N = int(input())
# 스택 변수를 만들어둔다.
Stack = deque()
# 입력받은 N만큼 명령을 처리할 예정
for _ in range(N):
# push일 경우 띄어쓰기로 정수 X도 입력받아야하므로, 통일성을 위해 리스트로 입력 받는다.
order = list(input().rstrip().split())
# 0번째 원소를 비교
match order[0]:
# push 명령일 때, 1번 인덱스(정수 X)를 입력해준다.
case "push":
# 따로 연산할 것도 아니라서 정수 변환 별도로 안해줌.
Stack.append(order[1])
# pop 명령일 때, try except 구문으로 예외처리 해줌
case "pop":
try:
print(Stack.pop())
except:
print(-1)
# size 명령일 때, 그냥 len 씌워줌
case "size":
print(len(Stack))
# empty 명령일 때, 스택 길이가 0이 아니면 0을 출력, 아니면 1 출력
case "empty":
if len(Stack): print(0)
else: print(1)
# top 명령일 때, pop과 동일하게 try except 구문으로 예외처리 함
case "top":
try:
print(Stack[-1])
except:
print(-1)
문제
정수를 저장하는 스택을 구현한 다음, 입력으로 주어지는 명령을 처리하는 프로그램을 작성하시오.
명령은 총 다섯 가지이다.
push X: 정수 X를 스택에 넣는 연산이다.
pop: 스택에서 가장 위에 있는 정수를 빼고, 그 수를 출력한다. 만약 스택에 들어있는 정수가 없는 경우에는 -1을 출력한다.
size: 스택에 들어있는 정수의 개수를 출력한다.
empty: 스택이 비어있으면 1, 아니면 0을 출력한다.
top: 스택의 가장 위에 있는 정수를 출력한다. 만약 스택에 들어있는 정수가 없는 경우에는 -1을 출력한다.
입력
첫째 줄에 주어지는 명령의 수 N (1 ≤ N ≤ 10,000)이 주어진다. 둘째 줄부터 N개의 줄에는 명령이 하나씩 주어진다. 주어지는 정수는 1보다 크거나 같고, 100,000보다 작거나 같다. 문제에 나와있지 않은 명령이 주어지는 경우는 없다.
출력
출력해야하는 명령이 주어질 때마다, 한 줄에 하나씩 출력한다.
제한
예제 입력 1
복사
14
push 1
push 2
top
size
empty
pop
pop
pop
size
empty
pop
push 3
empty
top
예제 출력 1
복사
2
2
0
2
1
-1
0
1
-1
0
3
예제 입력 2
복사
7
pop
top
push 123
top
pop
top
pop
예제 출력 2
복사
-1
-1
123
123
-1
-1
힌트
-
숫자 카드
출처 : 숫자 카드
Solution
Python
import sys
input = sys.stdin.readline
if __name__ == '__main__':
# 모두 차례차례 입력 받는다.
N = int(input())
cards = list(map(int, input().split()))
M = int(input())
check = list(map(int, input().split()))
# 정답 넣어둘 dict (배열로는 시간 초과 뜸)
answer = dict(zip(check, [0]*len(check)))
# cards 를 체크하면서 보유 중이면 1로 바꿈
for chk in cards:
# if 문 안 하면 새로운 키 값을 생성해버리니 주의!
if chk in answer.keys():
answer[chk] = 1
print(*answer.values())
문제
숫자 카드는 정수 하나가 적혀져 있는 카드이다. 상근이는 숫자 카드 N개를 가지고 있다. 정수 M개가 주어졌을 때, 이 수가 적혀있는 숫자 카드를 상근이가 가지고 있는지 아닌지를 구하는 프로그램을 작성하시오.
입력
첫째 줄에 상근이가 가지고 있는 숫자 카드의 개수 N(1 ≤ N ≤ 500,000)이 주어진다. 둘째 줄에는 숫자 카드에 적혀있는 정수가 주어진다. 숫자 카드에 적혀있는 수는 -10,000,000보다 크거나 같고, 10,000,000보다 작거나 같다. 두 숫자 카드에 같은 수가 적혀있는 경우는 없다.
셋째 줄에는 M(1 ≤ M ≤ 500,000)이 주어진다. 넷째 줄에는 상근이가 가지고 있는 숫자 카드인지 아닌지를 구해야 할 M개의 정수가 주어지며, 이 수는 공백으로 구분되어져 있다. 이 수도 -10,000,000보다 크거나 같고, 10,000,000보다 작거나 같다
출력
첫째 줄에 입력으로 주어진 M개의 수에 대해서, 각 수가 적힌 숫자 카드를 상근이가 가지고 있으면 1을, 아니면 0을 공백으로 구분해 출력한다.
제한
예제 입력 1
복사
5
6 3 2 10 -10
8
10 9 -5 2 3 4 5 -10
예제 출력 1
복사
1 0 0 1 1 0 0 1
힌트
-
감소하는 수
출처 : 감소하는 수
Solution
Python
import sys
input = sys.stdin.readline
from itertools import combinations
if __name__ == '__main__':
N = int(input())
# 9876543210 배열에서 나올 수 있는 자릿수는 1~10자리임
for n in range(1, 11):
# join 함수로 모든 경우의 수를 튜플에서 문자열로 바꿔주고, 작은 수부터 차례로 커지도록 정렬한다.
lst = sorted(list(map(''.join, combinations('9876543210', n))))
# 아직 N번째가 안됐으면, 체크한 감소하는 수 갯수만큼 N의 값을 줄여준다.
if N >= len(lst): N -= len(lst)
# 현재 리스트 안에 N번째 감소하는 수가 있으면,
else:
# 출력해주고, for 문 밖의 조건문에 안 걸리도록 빼준다.
print(lst[N])
N -= len(lst)
break
# 만약 for문 다 돌았는데 N이 0보다 크거나 같다면, -1을 출력 (감소하는 수가 없음)
if N >= 0: print(-1)
문제
음이 아닌 정수 X의 자릿수가 가장 큰 자릿수부터 작은 자릿수까지 감소한다면, 그 수를 감소하는 수라고 한다. 예를 들어, 321과 950은 감소하는 수지만, 322와 958은 아니다. N번째 감소하는 수를 출력하는 프로그램을 작성하시오. 0은 0번째 감소하는 수이고, 1은 1번째 감소하는 수이다. 만약 N번째 감소하는 수가 없다면 -1을 출력한다.
입력
첫째 줄에 N이 주어진다. N은 1,000,000보다 작거나 같은 자연수 또는 0이다.
출력
첫째 줄에 N번째 감소하는 수를 출력한다.
제한
예제 입력 1
복사
18
예제 출력 1
복사
42
예제 입력 2
복사
0
예제 출력 2
복사
0
예제 입력 3
복사
500000
예제 출력 3
복사
-1
힌트
-
적록색약
출처 : 적록색약
Solution
Python
import sys
# 재귀 함수 최대 깊이 / N 최대값이 100이므로, 100*100으로 한계를 늘려둔다.
sys.setrecursionlimit(100**2)
input = sys.stdin.readline
# 방문체크하는 2차원 배열 안에 확인 안 한 칸이 있는지 체크하는 함수
def checkBoard(board):
# 각 행씩 따로 체크하기 위해 for문 먼저 돌림
for i in range(len(board)):
# i행에 False가 있다면,
if False in board[i]:
# False가 있는 행과 열을 tuple 로 내보냄
return (i, board[i].index(False))
# 전부 체크했는데 False가 없다면, return 값을 False로 내보내서 while 문을 탈출함
return False
# 영역 갯수 세는 함수 (2차원배열의 그림, 해당 그림의 크기, 색약 유무 bool 값)
def calcRegion(board, N, color):
# 그림과 동일한 크기의 방문 체크 배열
visited = [[False]*N for _ in range(N)]
direction = ((-1, 0), (1, 0), (0, -1), (0, 1)) # 상하좌우
# 영역의 갯수를 저장할 변수
result = 0
# 방문배열 내 가장 먼저 등장하는 False 값 위치
s = checkBoard(visited)
# s 값이 있으면 반복됨(False가 되면 탈출)
while (s):
# s는 튜플값이므로, y와 x에 나눠서 배분
y, x = s[0], s[1]
# 해당 위치는 방문했다고 체크
visited[y][x] = True
# c는 그림에서 실제 RGB 값
c = board[y][x]
# 색약이 아니면 c를 그대로 배열로 만들고C에 넣어줌
if (not color): C = [c]
# 색약이라면,
else:
# c가 R, G 중 하나라면, R, G를 동일하게 보기위해 같은 배열로 넣음
if (c in ['R', 'G']): C = ['R', 'G']
else: C = ['B'] # 남은 색상 하나는 B니깐 그냥 B만 배열로 해줌
# 중첩 함수, visited를 인자로 안 받고 접근하기 위해 사용
def chkV(y, x, c):
# 4방향을 다 체크하면서
for dy, dx in direction:
ny, nx = y+dy, x+dx
# 배열 범위 안인지 우선 확인
if ((0 <= ny < N)and(0 <= nx < N)):
# 방문 안한 위치인지 확인하고, 같은 색상인지 확인(배열로 만들었으니 in으로 체크)
if ((not visited[ny][nx])and(board[ny][nx] in C)):
visited[ny][nx] = True # 같은 구역이라면 True
chkV(ny,nx,c) # dfs 로 다음 위치 탐색
# 만들어둔 중첩함수를 시행해서 c와 같은 구역은 방문체크 해줌
chkV(y,x,c)
# c와 같은 구역은 전부 탐색했으니 구역 수 +1
result += 1
# 체크되지 않은 다음 False 위치를 찾아서 s에 넣음, 이 때 False가 없다면 s가 False가 됨
s = checkBoard(visited)
return result
if __name__ == '__main__':
N = int(input())
canvas = [list(input().strip()) for _ in range(N)]
answer = [0,0]
answer[0] = calcRegion(canvas, N, False)
answer[1] = calcRegion(canvas, N, True)
print(*answer)
문제
적록색약은 빨간색과 초록색의 차이를 거의 느끼지 못한다. 따라서, 적록색약인 사람이 보는 그림은 아닌 사람이 보는 그림과는 좀 다를 수 있다.
크기가 N×N인 그리드의 각 칸에 R(빨강), G(초록), B(파랑) 중 하나를 색칠한 그림이 있다. 그림은 몇 개의 구역으로 나뉘어져 있는데, 구역은 같은 색으로 이루어져 있다. 또, 같은 색상이 상하좌우로 인접해 있는 경우에 두 글자는 같은 구역에 속한다. (색상의 차이를 거의 느끼지 못하는 경우도 같은 색상이라 한다)
예를 들어, 그림이 아래와 같은 경우에
RRRBB
GGBBB
BBBRR
BBRRR
RRRRR
적록색약이 아닌 사람이 봤을 때 구역의 수는 총 4개이다. (빨강 2, 파랑 1, 초록 1) 하지만, 적록색약인 사람은 구역을 3개 볼 수 있다. (빨강-초록 2, 파랑 1)
그림이 입력으로 주어졌을 때, 적록색약인 사람이 봤을 때와 아닌 사람이 봤을 때 구역의 수를 구하는 프로그램을 작성하시오.
입력
첫째 줄에 N이 주어진다. (1 ≤ N ≤ 100)
둘째 줄부터 N개 줄에는 그림이 주어진다.
출력
적록색약이 아닌 사람이 봤을 때의 구역의 개수와 적록색약인 사람이 봤을 때의 구역의 수를 공백으로 구분해 출력한다.
제한
예제 입력 1
복사
5
RRRBB
GGBBB
BBBRR
BBRRR
RRRRR
예제 출력 1
복사
4 3
힌트
W3sicHJvYmxlbV9pZCI6IjEwMDI2IiwicHJvYmxlbV9sYW5nIjoiMCIsInRpdGxlIjoiXHVjODAxXHViODVkXHVjMGM5XHVjNTdkIiwiZGVzY3JpcHRpb24iOiI8cD5cdWM4MDFcdWI4NWRcdWMwYzlcdWM1N2RcdWM3NDAgXHViZTY4XHVhYzA0XHVjMGM5XHVhY2ZjIFx1Y2QwOFx1Yjg1ZFx1YzBjOVx1Yzc1OCBcdWNjMjhcdWM3NzRcdWI5N2MgXHVhYzcwXHVjNzU4IFx1YjI5MFx1YjA3Y1x1YzljMCBcdWJhYmJcdWQ1NWNcdWIyZTQuIFx1YjUzMFx1Yjc3Y1x1YzExYywgXHVjODAxXHViODVkXHVjMGM5XHVjNTdkXHVjNzc4IFx1YzBhY1x1Yjc4Y1x1Yzc3NCBcdWJjZjRcdWIyOTQgXHVhZGY4XHViOWJjXHVjNzQwIFx1YzU0NFx1YjJjYyBcdWMwYWNcdWI3OGNcdWM3NzQgXHViY2Y0XHViMjk0IFx1YWRmOFx1YjliY1x1YWNmY1x1YjI5NCBcdWM4ODAgXHViMmU0XHViOTdjIFx1YzIxOCBcdWM3ODhcdWIyZTQuPFwvcD5cclxuXHJcbjxwPlx1ZDA2Y1x1YWUzMFx1YWMwMCBOJnRpbWVzO05cdWM3NzggXHVhZGY4XHViOWFjXHViNGRjXHVjNzU4IFx1YWMwMSBcdWNlNzhcdWM1ZDAgUihcdWJlNjhcdWFjMTUpLCBHKFx1Y2QwOFx1Yjg1ZCksIEIoXHVkMzBjXHViNzkxKSBcdWM5MTEgXHVkNTU4XHViMDk4XHViOTdjIFx1YzBjOVx1Y2U2MFx1ZDU1YyBcdWFkZjhcdWI5YmNcdWM3NzQgXHVjNzg4XHViMmU0LiBcdWFkZjhcdWI5YmNcdWM3NDAgXHViYTg3IFx1YWMxY1x1Yzc1OCBcdWFkNmNcdWM1ZWRcdWM3M2NcdWI4NWMgXHViMDk4XHViMjU4XHVjNWI0XHVjODM4IFx1Yzc4OFx1YjI5NFx1YjM3MCwgXHVhZDZjXHVjNWVkXHVjNzQwIFx1YWMxOVx1Yzc0MCBcdWMwYzlcdWM3M2NcdWI4NWMgXHVjNzc0XHViOGU4XHVjNWI0XHVjODM4IFx1Yzc4OFx1YjJlNC4gXHViNjEwLCBcdWFjMTlcdWM3NDAgXHVjMGM5XHVjMGMxXHVjNzc0IFx1YzBjMVx1ZDU1OFx1Yzg4Y1x1YzZiMFx1Yjg1YyBcdWM3NzhcdWM4MTFcdWQ1NzQgXHVjNzg4XHViMjk0IFx1YWNiZFx1YzZiMFx1YzVkMCBcdWI0NTAgXHVhZTAwXHVjNzkwXHViMjk0IFx1YWMxOVx1Yzc0MCBcdWFkNmNcdWM1ZWRcdWM1ZDAgXHVjMThkXHVkNTVjXHViMmU0LiAoXHVjMGM5XHVjMGMxXHVjNzU4IFx1Y2MyOFx1Yzc3NFx1Yjk3YyBcdWFjNzBcdWM3NTggXHViMjkwXHViMDdjXHVjOWMwIFx1YmFiYlx1ZDU1OFx1YjI5NCBcdWFjYmRcdWM2YjBcdWIzYzQgXHVhYzE5XHVjNzQwIFx1YzBjOVx1YzBjMVx1Yzc3NFx1Yjc3YyBcdWQ1NWNcdWIyZTQpPFwvcD5cclxuXHJcbjxwPlx1YzYwOFx1Yjk3YyBcdWI0ZTRcdWM1YjQsIFx1YWRmOFx1YjliY1x1Yzc3NCBcdWM1NDRcdWI3OThcdWM2NDAgXHVhYzE5XHVjNzQwIFx1YWNiZFx1YzZiMFx1YzVkMDxcL3A+XHJcblxyXG48cHJlPlxyXG5SUlJCQlxyXG5HR0JCQlxyXG5CQkJSUlxyXG5CQlJSUlxyXG5SUlJSUjxcL3ByZT5cclxuXHJcbjxwPlx1YzgwMVx1Yjg1ZFx1YzBjOVx1YzU3ZFx1Yzc3NCBcdWM1NDRcdWIyY2MgXHVjMGFjXHViNzhjXHVjNzc0IFx1YmQyNFx1Yzc0NCBcdWI1NGMgXHVhZDZjXHVjNWVkXHVjNzU4IFx1YzIxOFx1YjI5NCBcdWNkMWQgNFx1YWMxY1x1Yzc3NFx1YjJlNC4gKFx1YmU2OFx1YWMxNSAyLCBcdWQzMGNcdWI3OTEgMSwgXHVjZDA4XHViODVkIDEpIFx1ZDU1OFx1YzljMFx1YjljYywgXHVjODAxXHViODVkXHVjMGM5XHVjNTdkXHVjNzc4IFx1YzBhY1x1Yjc4Y1x1Yzc0MCBcdWFkNmNcdWM1ZWRcdWM3NDQgM1x1YWMxYyBcdWJjZmMgXHVjMjE4IFx1Yzc4OFx1YjJlNC4gKFx1YmU2OFx1YWMxNS1cdWNkMDhcdWI4NWQgMiwgXHVkMzBjXHViNzkxIDEpPFwvcD5cclxuXHJcbjxwPlx1YWRmOFx1YjliY1x1Yzc3NCBcdWM3ODVcdWI4MjVcdWM3M2NcdWI4NWMgXHVjOGZjXHVjNWI0XHVjODRjXHVjNzQ0IFx1YjU0YywgXHVjODAxXHViODVkXHVjMGM5XHVjNTdkXHVjNzc4IFx1YzBhY1x1Yjc4Y1x1Yzc3NCBcdWJkMjRcdWM3NDQgXHViNTRjXHVjNjQwIFx1YzU0NFx1YjJjYyBcdWMwYWNcdWI3OGNcdWM3NzQgXHViZDI0XHVjNzQ0IFx1YjU0YyBcdWFkNmNcdWM1ZWRcdWM3NTggXHVjMjE4XHViOTdjIFx1YWQ2Y1x1ZDU1OFx1YjI5NCBcdWQ1MDRcdWI4NWNcdWFkZjhcdWI3YThcdWM3NDQgXHVjNzkxXHVjMTMxXHVkNTU4XHVjMmRjXHVjNjI0LjxcL3A+XHJcbiIsImlucHV0IjoiPHA+XHVjY2FiXHVjOWY4IFx1YzkwNFx1YzVkMCBOXHVjNzc0IFx1YzhmY1x1YzViNFx1YzljNFx1YjJlNC4gKDEgJmxlOyBOICZsZTsgMTAwKTxcL3A+XHJcblxyXG48cD5cdWI0NThcdWM5ZjggXHVjOTA0XHViZDgwXHVkMTMwIE5cdWFjMWMgXHVjOTA0XHVjNWQwXHViMjk0IFx1YWRmOFx1YjliY1x1Yzc3NCBcdWM4ZmNcdWM1YjRcdWM5YzRcdWIyZTQuPFwvcD5cclxuIiwib3V0cHV0IjoiPHA+XHVjODAxXHViODVkXHVjMGM5XHVjNTdkXHVjNzc0IFx1YzU0NFx1YjJjYyBcdWMwYWNcdWI3OGNcdWM3NzQgXHViZDI0XHVjNzQ0IFx1YjU0Y1x1Yzc1OCBcdWFkNmNcdWM1ZWRcdWM3NTggXHVhYzFjXHVjMjE4XHVjNjQwIFx1YzgwMVx1Yjg1ZFx1YzBjOVx1YzU3ZFx1Yzc3OCBcdWMwYWNcdWI3OGNcdWM3NzQgXHViZDI0XHVjNzQ0IFx1YjU0Y1x1Yzc1OCBcdWFkNmNcdWM1ZWRcdWM3NTggXHVjMjE4XHViOTdjIFx1YWNmNVx1YmMzMVx1YzczY1x1Yjg1YyBcdWFkNmNcdWJkODRcdWQ1NzQgXHVjZDljXHViODI1XHVkNTVjXHViMmU0LjxcL3A+XHJcbiIsImhpbnQiOiIiLCJvcmlnaW5hbCI6IjAiLCJodG1sX3RpdGxlIjoiMCIsInByb2JsZW1fbGFuZ190Y29kZSI6IktvcmVhbiJ9LHsicHJvYmxlbV9pZCI6IjEwMDI2IiwicHJvYmxlbV9sYW5nIjoiMSIsInRpdGxlIjoiQ293IEFydCIsImRlc2NyaXB0aW9uIjoiPHA+QSBsaXR0bGUga25vd24gZmFjdCBhYm91dCBjb3dzIGlzIHRoZSBmYWN0IHRoYXQgdGhleSBhcmUgcmVkLWdyZWVuIGNvbG9yYmxpbmQsIG1lYW5pbmcgdGhhdCByZWQgYW5kIGdyZWVuIGxvb2sgaWRlbnRpY2FsIHRvIHRoZW0uICZuYnNwO1RoaXMgbWFrZXMgaXQgZXNwZWNpYWxseSBkaWZmaWN1bHQgdG8gZGVzaWduIGFydHdvcmsgdGhhdCBpcyBhcHBlYWxpbmcgdG8gY293cyBhcyB3ZWxsIGFzIGh1bWFucy48XC9wPlxyXG5cclxuPHA+Q29uc2lkZXIgYSBzcXVhcmUgcGFpbnRpbmcgdGhhdCBpcyBkZXNjcmliZWQgYnkgYW4gTiB4IE4gZ3JpZCBvZiBjaGFyYWN0ZXJzICgxICZsdDs9IE4gJmx0Oz0gMTAwKSwgZWFjaCBvbmUgZWl0aGVyIFIgKHJlZCksIEcgKGdyZWVuKSwgb3IgQiAoYmx1ZSkuICZuYnNwO0EgcGFpbnRpbmcgaXMgaW50ZXJlc3RpbmcgaWYgaXQgaGFzIG1hbnkgY29sb3JlZCAmcXVvdDtyZWdpb25zJnF1b3Q7IHRoYXQgY2FuIGJlIGRpc3Rpbmd1aXNoZWQgZnJvbSBlYWNoLW90aGVyLiAmbmJzcDtUd28gY2hhcmFjdGVycyBiZWxvbmcgdG8gdGhlIHNhbWUgcmVnaW9uIGlmIHRoZXkgYXJlIGRpcmVjdGx5IGFkamFjZW50IChlYXN0LCB3ZXN0LCBub3J0aCwgb3Igc291dGgpLCBhbmQgaWYgdGhleSBhcmUgaW5kaXN0aW5ndWlzaGFibGUgaW4gY29sb3IuICZuYnNwO0ZvciBleGFtcGxlLCB0aGUgcGFpbnRpbmc8XC9wPlxyXG5cclxuPHByZT5cclxuUlJSQkJcclxuR0dCQkJcclxuQkJCUlJcclxuQkJSUlJcclxuUlJSUlI8XC9wcmU+XHJcblxyXG48cD5oYXMgNCByZWdpb25zICgyIHJlZCwgMSBibHVlLCBhbmQgMSBncmVlbikgaWYgdmlld2VkIGJ5IGEgaHVtYW4sIGJ1dCBvbmx5IDNyZWdpb25zICgyIHJlZC1ncmVlbiwgMSBibHVlKSBpZiB2aWV3ZWQgYnkgYSBjb3cuICZuYnNwOzxcL3A+XHJcblxyXG48cD5HaXZlbiBhIHBhaW50aW5nIGFzIGlucHV0LCBwbGVhc2UgaGVscCBjb21wdXRlIHRoZSBudW1iZXIgb2YgcmVnaW9ucyBpbiB0aGUgcGFpbnRpbmcgd2hlbiB2aWV3ZWQgYnkgYSBodW1hbiBhbmQgYnkgYSBjb3cuPFwvcD5cclxuIiwiaW5wdXQiOiI8cD4qIExpbmUgMTogVGhlIGludGVnZXIgTi48XC9wPlxyXG5cclxuPHA+KiBMaW5lcyAyLi4xK046IEVhY2ggbGluZSBjb250YWlucyBhIHN0cmluZyB3aXRoIE4gY2hhcmFjdGVycywgZGVzY3JpYmluZyBvbmUgcm93IG9mIGEgcGFpbnRpbmcuPFwvcD5cclxuIiwib3V0cHV0IjoiPHA+KiBMaW5lIDE6IFR3byBzcGFjZS1zZXBhcmF0ZWQgaW50ZWdlcnMsIHRlbGxpbmcgdGhlIG51bWJlciBvZiByZWdpb25zIGluIHRoZSBwYWludGluZyB3aGVuIHZpZXdlZCBieSBhIGh1bWFuIGFuZCBieSBhIGNvdy48XC9wPlxyXG4iLCJoaW50IjoiIiwib3JpZ2luYWwiOiIxIiwiaHRtbF90aXRsZSI6IjAiLCJwcm9ibGVtX2xhbmdfdGNvZGUiOiJFbmdsaXNoIn1d
-
연산자 끼워넣기
출처 : 연산자 끼워넣기
Solution
Python
# 순열
from itertools import permutations
# 조합
from itertools import combinations
# list 내 같은 원소의 수 반환하는 함수
from collections import Counter
N = int(input())
A = input().split()
for i in range(N):
A[i] = int(A[i])
sum, min, mul, dev = map(int, input().split())
# 갯수로 입력받은 연산자를 배열 안에 하나씩 넣어준다.
arr = []
for i in range(sum):
arr.append('+')
for i in range(min):
arr.append('-')
for i in range(mul):
arr.append('*')
for i in range(dev):
arr.append('/')
# 연산자 순열을 중복없게 모든 경우의 수를 구한다.
arr = list(set(permutations(arr)))
# 연산해주는 함수를 별도로 만든다.
def cal(op, x, y):
match op:
case '+':
return x + y
case '-':
return x - y
case '*':
return x * y
case '/':
return x / y
# 최대 최소값 저장할 변수
M = -1000000000
m = 1000000000
# 모든 경우의 수를 돌면서 연산시작
for op in arr:
S = A[0]
for i in range(1, len(A)):
S = int(cal(op[i-1], S, A[i]))
# 최대값 최소값 배정
if (S > M):
M = S
if (S < m):
m = S
# 출력
print(M)
print(m)
문제
N개의 수로 이루어진 수열 A1, A2, ..., AN이 주어진다. 또, 수와 수 사이에 끼워넣을 수 있는 N-1개의 연산자가 주어진다. 연산자는 덧셈(+), 뺄셈(-), 곱셈(×), 나눗셈(÷)으로만 이루어져 있다.
우리는 수와 수 사이에 연산자를 하나씩 넣어서, 수식을 하나 만들 수 있다. 이때, 주어진 수의 순서를 바꾸면 안 된다.
예를 들어, 6개의 수로 이루어진 수열이 1, 2, 3, 4, 5, 6이고, 주어진 연산자가 덧셈(+) 2개, 뺄셈(-) 1개, 곱셈(×) 1개, 나눗셈(÷) 1개인 경우에는 총 60가지의 식을 만들 수 있다. 예를 들어, 아래와 같은 식을 만들 수 있다.
1+2+3-4×5÷6
1÷2+3+4-5×6
1+2÷3×4-5+6
1÷2×3-4+5+6
식의 계산은 연산자 우선 순위를 무시하고 앞에서부터 진행해야 한다. 또, 나눗셈은 정수 나눗셈으로 몫만 취한다. 음수를 양수로 나눌 때는 C++14의 기준을 따른다. 즉, 양수로 바꾼 뒤 몫을 취하고, 그 몫을 음수로 바꾼 것과 같다. 이에 따라서, 위의 식 4개의 결과를 계산해보면 아래와 같다.
1+2+3-4×5÷6 = 1
1÷2+3+4-5×6 = 12
1+2÷3×4-5+6 = 5
1÷2×3-4+5+6 = 7
N개의 수와 N-1개의 연산자가 주어졌을 때, 만들 수 있는 식의 결과가 최대인 것과 최소인 것을 구하는 프로그램을 작성하시오.
입력
첫째 줄에 수의 개수 N(2 ≤ N ≤ 11)가 주어진다. 둘째 줄에는 A1, A2, ..., AN이 주어진다. (1 ≤ Ai ≤ 100) 셋째 줄에는 합이 N-1인 4개의 정수가 주어지는데, 차례대로 덧셈(+)의 개수, 뺄셈(-)의 개수, 곱셈(×)의 개수, 나눗셈(÷)의 개수이다.
출력
첫째 줄에 만들 수 있는 식의 결과의 최댓값을, 둘째 줄에는 최솟값을 출력한다. 연산자를 어떻게 끼워넣어도 항상 -10억보다 크거나 같고, 10억보다 작거나 같은 결과가 나오는 입력만 주어진다. 또한, 앞에서부터 계산했을 때, 중간에 계산되는 식의 결과도 항상 -10억보다 크거나 같고, 10억보다 작거나 같다.
제한
예제 입력 1
복사
2
5 6
0 0 1 0
예제 출력 1
복사
30
30
예제 입력 2
복사
3
3 4 5
1 0 1 0
예제 출력 2
복사
35
17
예제 입력 3
복사
6
1 2 3 4 5 6
2 1 1 1
예제 출력 3
복사
54
-24
힌트
세 번째 예제의 경우에 다음과 같은 식이 최댓값/최솟값이 나온다.
최댓값: 1-2÷3+4+5×6
최솟값: 1+2+3÷4-5×6
Touch background to close