728x90
반응형

문제:

크기가 N×N인 도시가 있다. 도시는 1×1크기의 칸으로 나누어져 있다. 도시의 각 칸은 빈 칸, 치킨집, 집 중 하나이다. 도시의 칸은 (r, c)와 같은 형태로 나타내고, r행 c열 또는 위에서부터 r번째 칸, 왼쪽에서부터 c번째 칸을 의미한다. r과 c는 1부터 시작한다.

이 도시에 사는 사람들은 치킨을 매우 좋아한다. 따라서, 사람들은 "치킨 거리"라는 말을 주로 사용한다. 치킨 거리는 집과 가장 가까운 치킨집 사이의 거리이다. 즉, 치킨 거리는 집을 기준으로 정해지며, 각각의 집은 치킨 거리를 가지고 있다. 도시의 치킨 거리는 모든 집의 치킨 거리의 합이다.

임의의 두 칸 (r1, c1)과 (r2, c2) 사이의 거리는 |r1-r2| + |c1-c2|로 구한다.

예를 들어, 아래와 같은 지도를 갖는 도시를 살펴보자.

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개를 골랐을 때, 도시의 치킨 거리의 최솟값을 출력한다.

풀이방법:

 치킨집들 중에서 임의의 M개의 치킨집을 골라 폐업시킨 뒤, 도시의 치킨 거리를 구한다. 그리고 이 과정을 가능한 모든 조합에 대해서 수행하고, 그 중 가장 최솟값인 도시의 치킨 거리를 출력한다.

 처음 입력을 받을 때 치킨집과 집과의 치킨 거리를 계산을 하고, itertools를 사용해 모든 폐업 조합(남아 있는 집)을 구한다. 남아 있는 집에 대해서 사전에 구했던 치킨 거리들을 합산함으로써 답을 얻는다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
import itertools
 
n,m = map(int,input().split())
chicken = []
person = [] 
for i in range(n):
    row = list(map(int,input().split()))
    for j,r in enumerate(row):
        if r == 1:
            person.append((j,i))
        elif r==2:
            chicken.append((j,i))
 
distance = dict()
for c in chicken:
    for i,p in enumerate(person):
        if distance.get(c):
            distance[c][i] = abs(p[0]-c[0])+abs(p[1]-c[1])
        else:
            distance[c]=[0]*len(person)
            distance[c][i] = abs(p[0]-c[0])+abs(p[1]-c[1])
            
survivedChicken = list(itertools.combinations(chicken,m))
answer = float('inf')
for survived in survivedChicken:
    candidated = [float('inf')]*len(person)
    for su in survived:
        for i,d in enumerate(distance[su]):
            if candidated[i] > d:
                candidated[i] = d
    if answer > sum(candidated):
        answer = sum(candidated)
print(answer)
cs

문제링크:

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

 

15686번: 치킨 배달

크기가 N×N인 도시가 있다. 도시는 1×1크기의 칸으로 나누어져 있다. 도시의 각 칸은 빈 칸, 치킨집, 집 중 하나이다. 도시의 칸은 (r, c)와 같은 형태로 나타내고, r행 c열 또는 위에서부터 r번째 칸

www.acmicpc.net

 

728x90
반응형

'Algorithm > Python' 카테고리의 다른 글

[BOJ]1826. 연료 채우기  (0) 2021.05.27
[BOJ]1422. 숫자의 신  (0) 2021.05.25
[BOJ]2583. 영역 구하기  (0) 2021.05.18
[BOJ]3055. 탈출  (0) 2021.05.11
[BOJ]2630. 색종이 만들기  (0) 2021.04.29
728x90
반응형

문제:

눈금의 간격이 1인 M×N(M,N≤100)크기의 모눈종이가 있다. 이 모눈종이 위에 눈금에 맞추어 K개의 직사각형을 그릴 때, 이들 K개의 직사각형의 내부를 제외한 나머지 부분이 몇 개의 분리된 영역으로 나누어진다.

예를 들어 M=5, N=7 인 모눈종이 위에 <그림 1>과 같이 직사각형 3개를 그렸다면, 그 나머지 영역은 <그림 2>와 같이 3개의 분리된 영역으로 나누어지게 된다.

<그림 2>와 같이 분리된 세 영역의 넓이는 각각 1, 7, 13이 된다.

M, N과 K 그리고 K개의 직사각형의 좌표가 주어질 때, K개의 직사각형 내부를 제외한 나머지 부분이 몇 개의 분리된 영역으로 나누어지는지, 그리고 분리된 각 영역의 넓이가 얼마인지를 구하여 이를 출력하는 프로그램을 작성하시오.

입력:

첫째 줄에 M과 N, 그리고 K가 빈칸을 사이에 두고 차례로 주어진다. M, N, K는 모두 100 이하의 자연수이다. 둘째 줄부터 K개의 줄에는 한 줄에 하나씩 직사각형의 왼쪽 아래 꼭짓점의 x, y좌표값과 오른쪽 위 꼭짓점의 x, y좌표값이 빈칸을 사이에 두고 차례로 주어진다. 모눈종이의 왼쪽 아래 꼭짓점의 좌표는 (0,0)이고, 오른쪽 위 꼭짓점의 좌표는(N,M)이다. 입력되는 K개의 직사각형들이 모눈종이 전체를 채우는 경우는 없다.

출력:

첫째 줄에 분리되어 나누어지는 영역의 개수를 출력한다. 둘째 줄에는 각 영역의 넓이를 오름차순으로 정렬하여 빈칸을 사이에 두고 출력한다.

풀이방법:

 bfs를 사용하여 각 직사각형의 내부를 제외한 나머지 부분이 몇 개의 분리된 영역들의 넓이를 구한다. 전체 영역을 1로 초기화하고 직사각형의 꼭짓점을 입력값으로 받을 때, 내부 영역들을 0으로 재정의한다.

 이 과정을 모두 마친 뒤, (0,0)부터 bfs를 사용하여 분리된 영역들의 각 넓이를 구한다. 한 점으로부터 시작해 이동하면서 visited를 업데이트하여 중복적으로 이동하는 것을 막으며 더 이상 이동하지 못할 때, 하나의 분리된 영역의 넓이를 구한 것으로 파악한다.

 탐색하는 과정을 region이 1이고, 방문하지 않은(visited가 0인) 곳에 대해 반복적으로 BFS를 수행하고, 이 결과들을 출력한다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
dx = [-1,0,0,1]
dy = [0,1,-1,0]
 
def bfs(x,y):
    visited[y][x] = 1
    area = 1
    points = [(x,y)]
    while len(points):
        temp = []
        for point in points:
            x,y = point
            for i in range(4):
                nx = x+dx[i]
                ny = y+dy[i]
                if 0<= nx < n and 0<= ny < m:
                    if region[ny][nx]==1 and not visited[ny][nx]:
                        area+=1
                        visited[ny][nx]=1
                        temp.append((nx,ny))
        points = temp
    return area
                
 
m,n,k = map(int,input().split())
region = [[1 for _ in range(n)]for _ in range(m)]
visited = [[0 for _ in range(n)]for _ in range(m)]
 
for _ in range(k):
    x1,y1,x2,y2 = map(int,input().split())
    for x in range(x1,x2):
        for y in range(y1,y2):
            region[y][x] = 0
 
 
answers = []
for x in range(n):
    for y in range(m):
        if region[y][x] and not visited[y][x]:
            answer = bfs(x,y)
            answers.append(answer)
            
print(len(answers))
print(*sorted(answers))
cs

문제링크:

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

728x90
반응형

'Algorithm > Python' 카테고리의 다른 글

[BOJ]1422. 숫자의 신  (0) 2021.05.25
[BOJ]15686. 치킨 배달  (0) 2021.05.20
[BOJ]3055. 탈출  (0) 2021.05.11
[BOJ]2630. 색종이 만들기  (0) 2021.04.29
[BOJ]3273. 두 수의 합  (0) 2021.04.27
728x90
반응형

문제:

사악한 암흑의 군주 이민혁은 드디어 마법 구슬을 손에 넣었고, 그 능력을 실험해보기 위해 근처의 티떱숲에 홍수를 일으키려고 한다. 이 숲에는 고슴도치가 한 마리 살고 있다. 고슴도치는 제일 친한 친구인 비버의 굴로 가능한 빨리 도망가 홍수를 피하려고 한다.

티떱숲의 지도는 R행 C열로 이루어져 있다. 비어있는 곳은 '.'로 표시되어 있고, 물이 차있는 지역은 '*', 돌은 'X'로 표시되어 있다. 비버의 굴은 'D'로, 고슴도치의 위치는 'S'로 나타내어져 있다.

매 분마다 고슴도치는 현재 있는 칸과 인접한 네 칸 중 하나로 이동할 수 있다. (위, 아래, 오른쪽, 왼쪽) 물도 매 분마다 비어있는 칸으로 확장한다. 물이 있는 칸과 인접해있는 비어있는 칸(적어도 한 변을 공유)은 물이 차게 된다. 물과 고슴도치는 돌을 통과할 수 없다. 또, 고슴도치는 물로 차있는 구역으로 이동할 수 없고, 물도 비버의 소굴로 이동할 수 없다.

티떱숲의 지도가 주어졌을 때, 고슴도치가 안전하게 비버의 굴로 이동하기 위해 필요한 최소 시간을 구하는 프로그램을 작성하시오.

고슴도치는 물이 찰 예정인 칸으로 이동할 수 없다. 즉, 다음 시간에 물이 찰 예정인 칸으로 고슴도치는 이동할 수 없다. 이동할 수 있으면 고슴도치가 물에 빠지기 때문이다. 

입력:

첫째 줄에 50보다 작거나 같은 자연수 R과 C가 주어진다.

다음 R개 줄에는 티떱숲의 지도가 주어지며, 문제에서 설명한 문자만 주어진다. 'D'와 'S'는 하나씩만 주어진다.

출력:

첫째 줄에 고슴도치가 비버의 굴로 이동할 수 있는 가장 빠른 시간을 출력한다. 만약, 안전하게 비버의 굴로 이동할 수 없다면, "KAKTUS"를 출력한다.

풀이방법:

 이 문제의 핵심은 물과 고슴도치의 이동을 BFS로 확인하면서 고슴도치가 비버의 집까지 갈 때까지 물의 영향을 받지 않는 지 확인해야 한다.

 우선 물에 대해서 BFS를 수행하면서 한 번 퍼질 때마다 1씩 늘어나면서 visit 배열이 채워진다. 이 때, 벽이나 비버의 집에는 물이 차지 않도록 한다.

 그 다음에는 고슴도치의 이동에 대해서 BFS를 수행하며 배열 안에 존재하며 비버의 집을 찾을 때 종료되도록 한다. 고슴도치가 이동할 때에는 물이 퍼진 정도에 따라 이동을 할 수 있으며, 물의 visit 배열 값보다 작을 때에만 이동할 수 있다. (물의 값이 4, 고슴도치가 이동할 값이 5라면 이동 불가 -> 물이 이미 차 있기 때문)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
def main():
    from collections import deque
 
    dx = [-1,0,1,0]
    dy = [0,1,0,-1]
 
    r,c = map(int,input().split())
    hVisit = [[0 for _ in range(c)]for _ in range(r)]
    wVisit = [[0 for _ in range(c)]for _ in range(r)]
    forest = []
    Hedgehog = deque()
    water = deque()
    for i in range(r):
        temp = input()
        forest.append([])
        for j,t in enumerate(temp):
            if t == "X":
                forest[i].append(-1)
            elif t == "S":
                forest[i].append(1)
                Hedgehog.append((i,j))
                hVisit[i][j] = 1
            elif t == "*":
                forest[i].append(2)
                water.append((i,j))
                wVisit[i][j] = 1
            elif t == '.':
                forest[i].append(0)
            elif t == 'D':
                forest[i].append(3)
 
    while len(water):
        x,y = water.popleft()
        for i in range(4):
            nx = x + dx[i]
            ny = y + dy[i]
 
            if 0<=nx<and 0<=ny<and (forest[nx][ny]!=-1 and forest[nx][ny]!=3and not wVisit[nx][ny]:
                water.append((nx,ny))
                wVisit[nx][ny] = wVisit[x][y] + 1
    while len(Hedgehog):
        x,y = Hedgehog.popleft()
        for i in range(4):
            nx = x + dx[i]
            ny = y + dy[i]
            if 0<=nx<and 0<=ny<and forest[nx][ny]==3:
                print(hVisit[x][y])
                return 0
            if 0<=nx<and 0<=ny<c:
                if forest[nx][ny] != -1 and not hVisit[nx][ny]:
                    if hVisit[x][y] + 1 < wVisit[nx][ny] or wVisit[nx][ny] == 0:
                        Hedgehog.append((nx,ny))
                        hVisit[nx][ny] = hVisit[x][y] +1
 
    print("KAKTUS")
    
if __name__ == "__main__":
    main()
cs

문제링크:

www.acmicpc.net/problem/3055

 

3055번: 탈출

사악한 암흑의 군주 이민혁은 드디어 마법 구슬을 손에 넣었고, 그 능력을 실험해보기 위해 근처의 티떱숲에 홍수를 일으키려고 한다. 이 숲에는 고슴도치가 한 마리 살고 있다. 고슴도치는 제

www.acmicpc.net

 

728x90
반응형

'Algorithm > Python' 카테고리의 다른 글

[BOJ]15686. 치킨 배달  (0) 2021.05.20
[BOJ]2583. 영역 구하기  (0) 2021.05.18
[BOJ]2630. 색종이 만들기  (0) 2021.04.29
[BOJ]3273. 두 수의 합  (0) 2021.04.27
[BOJ]9184. 신나는 함수 실행  (0) 2021.04.22
728x90
반응형

문제:

아래 <그림 1>과 같이 여러개의 정사각형칸들로 이루어진 정사각형 모양의 종이가 주어져 있고, 각 정사각형들은 하얀색으로 칠해져 있거나 파란색으로 칠해져 있다. 주어진 종이를 일정한 규칙에 따라 잘라서 다양한 크기를 가진 정사각형 모양의 하얀색 또는 파란색 색종이를 만들려고 한다.

전체 종이의 크기가 N×N(N=2k, k는 1 이상 7 이하의 자연수) 이라면 종이를 자르는 규칙은 다음과 같다.

전체 종이가 모두 같은 색으로 칠해져 있지 않으면 가로와 세로로 중간 부분을 잘라서 <그림 2>의 I, II, III, IV와 같이 똑같은 크기의 네 개의 N/2 × N/2색종이로 나눈다. 나누어진 종이 I, II, III, IV 각각에 대해서도 앞에서와 마찬가지로 모두 같은 색으로 칠해져 있지 않으면 같은 방법으로 똑같은 크기의 네 개의 색종이로 나눈다. 이와 같은 과정을 잘라진 종이가 모두 하얀색 또는 모두 파란색으로 칠해져 있거나, 하나의 정사각형 칸이 되어 더 이상 자를 수 없을 때까지 반복한다.

위와 같은 규칙에 따라 잘랐을 때 <그림 3>은 <그림 1>의 종이를 처음 나눈 후의 상태를, <그림 4>는 두 번째 나눈 후의 상태를, <그림 5>는 최종적으로 만들어진 다양한 크기의 9장의 하얀색 색종이와 7장의 파란색 색종이를 보여주고 있다.

입력으로 주어진 종이의 한 변의 길이 N과 각 정사각형칸의 색(하얀색 또는 파란색)이 주어질 때 잘라진 하얀색 색종이와 파란색 색종이의 개수를 구하는 프로그램을 작성하시오.

입력:

첫째 줄에는 전체 종이의 한 변의 길이 N이 주어져 있다. N은 2, 4, 8, 16, 32, 64, 128 중 하나이다. 색종이의 각 가로줄의 정사각형칸들의 색이 윗줄부터 차례로 둘째 줄부터 마지막 줄까지 주어진다. 하얀색으로 칠해진 칸은 0, 파란색으로 칠해진 칸은 1로 주어지며, 각 숫자 사이에는 빈칸이 하나씩 있다.

출력:

첫째 줄에는 잘라진 햐얀색 색종이의 개수를 출력하고, 둘째 줄에는 파란색 색종이의 개수를 출력한다.

풀이방법:

반복해서 반으로 나누고 조건을 파악하는 대표적인 분할 정복문제다.

0,0부터 시작해서 check라는 함수를 통해서 이 색종이가 '흰색', '검은색', '나눠야함' 인지 확인한다. 확인하는 방법은 왼쪽 위의 색깔을 기준으로 삼고, 색종이의 크기만큼 반복문을 통해서 모두 같은 색깔인지 체크한다.

이렇게 white나 black이 나온다면 갯수를 더해주고 종료를 하고, 만약 나눠야 한다면 4개 사각형으로 나눠서 다시 한번 check하는 과정을 거치도록 한다.

반복문을 사용하면서 색깔을 확인하는 방식이기때문에 알아서 더 이상 나눌 수 없다면 종료하게 된다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
white, black = 00
 
def check(x,y,n):
    color = paper[x][y]
    div = False
    for i in range(n):
        for j in range(n):
            if color !=paper[x+i][y+j]:
                div = True
                break
    if div:
        return "div"
    else:
        if color == 0:
            return "white"
        else:
            return "black"
                
def divide(x,y,n):
    global white,black
    color = check(x,y,n)
    if color == 'white':
        white+=1
    elif color == 'black':
        black+=1
    else:
        divide(x,y,n//2)
        divide(x+n//2,y,n//2)
        divide(x,y+n//2,n//2)
        divide(x+n//2,y+n//2,n//2)
 
= int(input())
paper = []
for i in range(n):
    paper.append(list(map(int,input().split())))
 
divide(0,0,n)
print(white)
print(black)
cs

문제링크:

www.acmicpc.net/problem/2630

 

2630번: 색종이 만들기

첫째 줄에는 전체 종이의 한 변의 길이 N이 주어져 있다. N은 2, 4, 8, 16, 32, 64, 128 중 하나이다. 색종이의 각 가로줄의 정사각형칸들의 색이 윗줄부터 차례로 둘째 줄부터 마지막 줄까지 주어진다.

www.acmicpc.net

 

728x90
반응형

'Algorithm > Python' 카테고리의 다른 글

[BOJ]2583. 영역 구하기  (0) 2021.05.18
[BOJ]3055. 탈출  (0) 2021.05.11
[BOJ]3273. 두 수의 합  (0) 2021.04.27
[BOJ]9184. 신나는 함수 실행  (0) 2021.04.22
[BOJ]2981. 검문  (0) 2021.04.20
728x90
반응형

문제:

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)

출력:

문제의 조건을 만족하는 쌍의 개수를 출력한다.

풀이방법:

 앞에서부터 시작하는 포인터와 뒤에서부터 시작하는 포인터 두 개를 사용해서 합이 x가 되는 점들을 찾는다. 탐색이 종료되는 조건은 포인터가 교차하는 순간이며, 탐색하기 전에 정렬을 하도록 한다.

 

포인터의 이동은 다음과 같은 조건에 따른다.

 1. 두 포인터의 값이 x와 같다면, 양 포인터를 모두 이동시킨다.

 2. x보다 작다면 앞 포인터를 움직여 값을 키운다. 

 3. x보다 크다면 뒷 포인터를 움직여 값을 낮춘다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
= int(input())
numbers = list(map(int,input().split()))
numbers = sorted(numbers)
= int(input())
first, second = 0,n-1
answer = 0
while True:
    if first == second or first > second or second < first:
        break
    now = numbers[first]+numbers[second]
    if now == x:
        answer+=1
        first+=1
        second-=1
    elif now < x:
        first +=1
    else:
        second -=1
 
print(answer)
cs

문제링크:

www.acmicpc.net/problem/3273

 

3273번: 두 수의 합

n개의 서로 다른 양의 정수 a1, a2, ..., an으로 이루어진 수열이 있다. ai의 값은 1보다 크거나 같고, 1000000보다 작거나 같은 자연수이다. 자연수 x가 주어졌을 때, ai + aj = x (1 ≤ i < j ≤ n)을 만족하는

www.acmicpc.net

 

728x90
반응형

'Algorithm > Python' 카테고리의 다른 글

[BOJ]3055. 탈출  (0) 2021.05.11
[BOJ]2630. 색종이 만들기  (0) 2021.04.29
[BOJ]9184. 신나는 함수 실행  (0) 2021.04.22
[BOJ]2981. 검문  (0) 2021.04.20
[BOJ]10819. 차이를 최대로  (0) 2021.02.25
728x90
반응형

문제:

재귀 호출만 생각하면 신이 난다! 아닌가요?

다음과 같은 재귀함수 w(a, b, c)가 있다.

 

위의 함수를 구현하는 것은 매우 쉽다. 하지만, 그대로 구현하면 값을 구하는데 매우 오랜 시간이 걸린다. (예를 들면, a=15, b=15, c=15)

a, b, c가 주어졌을 때, w(a, b, c)를 출력하는 프로그램을 작성하시오.

입력:

입력은 세 정수 a, b, c로 이루어져 있으며, 한 줄에 하나씩 주어진다. 입력의 마지막은 -1 -1 -1로 나타내며, 세 정수가 모두 -1인 경우는 입력의 마지막을 제외하면 없다.

출력:

입력으로 주어진 각각의 a, b, c에 대해서, w(a, b, c)를 출력한다.

풀이방법:

그냥 이 함수를 재귀로 구성하면 시간초과가 발생하게 된다. 따라서 각 결과를 dp 테이블에 저장함으로써 시간을 단축시키도록 한다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
dp= [[[0 for _ in range(21)]for _ in range(21)]for _ in range(21)]
 
def w(a,b,c):
    if a<=0 or b<=0 or c<=0:
        return 1
    if a > 20 or b > 20 or c >20:
        return w(20,20,20)
    temp = dp[a][b][c]
    if temp!=0:
        return temp
    if a < b and b < c:
        ans = w(a,b,c-1)+w(a,b-1,c-1)-w(a,b-1,c)
        dp[a][b][c]=ans
        return ans
    else:
        ans = w(a-1,b,c)+w(a-1,b-1,c)+w(a-1,b,c-1)-w(a-1,b-1,c-1)
        dp[a][b][c]=ans
        return ans
 
while True:
    a,b,c=map(int,input().split())
    if a==-1 and b==-1 and c==-1:
        break
    else:
        print("w({}, {}, {}) =".format(a,b,c),w(a,b,c))
cs

문제링크:

www.acmicpc.net/problem/9184

 

9184번: 신나는 함수 실행

입력은 세 정수 a, b, c로 이루어져 있으며, 한 줄에 하나씩 주어진다. 입력의 마지막은 -1 -1 -1로 나타내며, 세 정수가 모두 -1인 경우는 입력의 마지막을 제외하면 없다.

www.acmicpc.net

 

728x90
반응형

'Algorithm > Python' 카테고리의 다른 글

[BOJ]2630. 색종이 만들기  (0) 2021.04.29
[BOJ]3273. 두 수의 합  (0) 2021.04.27
[BOJ]2981. 검문  (0) 2021.04.20
[BOJ]10819. 차이를 최대로  (0) 2021.02.25
[BOJ]14888. 연산자 끼워넣기  (0) 2021.02.23
728x90
반응형

문제:

트럭을 타고 이동하던 상근이는 경찰의 검문을 받게 되었다. 경찰은 상근이가 운반하던 화물을 하나하나 모두 확인할 것이기 때문에, 검문하는데 엄청나게 오랜 시간이 걸린다.

상근이는 시간을 때우기 위해서 수학 게임을 하기로 했다.

먼저 근처에 보이는 숫자 N개를 종이에 적는다. 그 다음, 종이에 적은 수를 M으로 나누었을 때, 나머지가 모두 같게 되는 M을 모두 찾으려고 한다. M은 1보다 커야 한다.

N개의 수가 주어졌을 때, 가능한 M을 모두 찾는 프로그램을 작성하시오.

입력:

첫째 줄에 종이에 적은 수의 개수 N이 주어진다. (2 ≤ N ≤ 100)

다음 줄부터 N개 줄에는 종이에 적은 수가 하나씩 주어진다. 이 수는 모두 1보다 크거나 같고, 1,000,000,000보다 작거나 같은 자연수이다. 같은 수가 두 번 이상 주어지지 않는다.

항상 M이 하나 이상 존재하는 경우만 입력으로 주어진다.

출력:

첫째 줄에 가능한 M을 공백으로 구분하여 모두 출력한다. 이때, M은 증가하는 순서이어야 한다.

풀이방법:

 N개의 숫자들을 M으로 나눴을 때 나머지가 모두 같은 M을 찾기 위해서는 N개의 숫자들을 큰 순서로 정렬한 뒤에 그들의 차를 구하고 GCD를 계산하면 된다. 이 것이 가능한 이유는 간략히 설명하면 다음과 같다. 

 

 숫자 A, B가 있고 M으로 나누면 나머지가 R로 같다고 하자. 그러면 다음과 같이 식으로 쓸 수 있다.

 

A = a*M + R

B = b*M + R

 

이들의 차를 구하면 다음과 같이 된다.

 

A-B = (a-b)*M

 

따라서 M은 A와 B의 GCD를 의미하게 되고 가능한 M은 해당 GCD들의 약수일 것이다.

 

python의 math.gcd를 사용하고, 이 값에 대해 약수를 구하는 함수를 구해 M을 출력하도록 한다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
from math import gcd,sqrt
 
def divisor(n):
    divList = {n}
    for i in range(2,int(sqrt(n)+1)):
        if n%i==0:
            divList.add(i)
            divList.add(n//i)
    divList = sorted(list(divList))
    return divList
    
 
= int(input())
numbers=[]
for _ in range(n):
    numbers.append(int(input()))
numbers.sort(reverse=True)    
 
diff = []
for i in range(len(numbers)-1):
    diff.append(numbers[i]-numbers[i-1])
    
answer = diff[0]
for i in range(1,len(diff)):
    answer = gcd(answer,diff[i])
 
print(*divisor(answer))
cs

문제링크:

www.acmicpc.net/problem/2981

728x90
반응형

'Algorithm > Python' 카테고리의 다른 글

[BOJ]3273. 두 수의 합  (0) 2021.04.27
[BOJ]9184. 신나는 함수 실행  (0) 2021.04.22
[BOJ]10819. 차이를 최대로  (0) 2021.02.25
[BOJ]14888. 연산자 끼워넣기  (0) 2021.02.23
[BOJ]2885. 초콜릿 식사  (0) 2021.02.16
728x90
반응형

문제:

N개의 정수로 이루어진 배열 A가 주어진다. 이때, 배열에 들어있는 정수의 순서를 적절히 바꿔서 다음 식의 최댓값을 구하는 프로그램을 작성하시오.

|A[0] - A[1]| + |A[1] - A[2]| + ... + |A[N-2] - A[N-1]|

입력:

첫째 줄에 N (3 ≤ N ≤ 8)이 주어진다. 둘째 줄에는 배열 A에 들어있는 정수가 주어진다. 배열에 들어있는 정수는 -100보다 크거나 같고, 100보다 작거나 같다.

출력:

첫째 줄에 배열에 들어있는 수의 순서를 적절히 바꿔서 얻을 수 있는 식의 최댓값을 출력한다.

풀이방법:

 뭔가 그리디한 방법을 사용해서도 풀 수 있는 방법이 있을 것 같지만, 경우의 수가 적으므로 이 문제 역시 permutation을 사용해서 모든 경우의 수를 만들어줌으로써 풀었다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
import itertools
 
= int(input())
numbers = list(map(int,input().split()))
 
candidates = list(itertools.permutations(numbers,n))
answer = 0
for can in candidates:
    temp = 0
    for i in range(n-1):
        temp += abs(can[i]-can[i+1])
    if answer < temp:
        answer = temp
print(answer)
cs

문제링크:

www.acmicpc.net/problem/10819

 

10819번: 차이를 최대로

첫째 줄에 N (3 ≤ N ≤ 8)이 주어진다. 둘째 줄에는 배열 A에 들어있는 정수가 주어진다. 배열에 들어있는 정수는 -100보다 크거나 같고, 100보다 작거나 같다.

www.acmicpc.net

 

728x90
반응형

'Algorithm > Python' 카테고리의 다른 글

[BOJ]9184. 신나는 함수 실행  (0) 2021.04.22
[BOJ]2981. 검문  (0) 2021.04.20
[BOJ]14888. 연산자 끼워넣기  (0) 2021.02.23
[BOJ]2885. 초콜릿 식사  (0) 2021.02.16
[BOJ]2621. 카드게임  (0) 2021.02.09
728x90
반응형

문제:

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억보다 작거나 같다.

풀이방법:

***pypy3으로 통과한 문제입니다.***

 브루트포스 알고리즘을 이용하기 위해 itertools의 permutation을 사용해서 모든 경우의 수를 만들어준다. 만들어진 경우의 수에 따라 조건문으로 알맞게 계산하면 된다. 단, 음수에 대한 나눗셈은 정해진 기준에 맞게 계산되도록 해준다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
import sys
 
input = sys.stdin.readline
 
= int(input())
numbers = list(map(int,input().split()))
op = list(map(int,input().split()))
temp = []
 
for i in range(0,4):
    for j in range(0,op[i]):
        temp.append(str(i))
        
import itertools
 
candidates = list(itertools.permutations(temp,n-1))
 
maxAns = -float('inf')
minAns = float('inf')
for can in candidates:
    res = numbers[0]
    for i,v in enumerate(can):
        if v=='0':
            res+=numbers[i+1]
        elif v=='1':
            res-=numbers[i+1]
        elif v=='2':
            res*=numbers[i+1]
        elif v=='3':
            if res < 0:
                res = -(abs(res)//numbers[i+1])
            else:
                res//=numbers[i+1]
    if maxAns < res:
        maxAns = res
    if minAns > res:
        minAns = res
        
print(maxAns)
print(minAns)
cs

문제링크:

www.acmicpc.net/problem/14888

 

14888번: 연산자 끼워넣기

첫째 줄에 수의 개수 N(2 ≤ N ≤ 11)가 주어진다. 둘째 줄에는 A1, A2, ..., AN이 주어진다. (1 ≤ Ai ≤ 100) 셋째 줄에는 합이 N-1인 4개의 정수가 주어지는데, 차례대로 덧셈(+)의 개수, 뺄셈(-)의 개수, 

www.acmicpc.net

 

728x90
반응형

'Algorithm > Python' 카테고리의 다른 글

[BOJ]2981. 검문  (0) 2021.04.20
[BOJ]10819. 차이를 최대로  (0) 2021.02.25
[BOJ]2885. 초콜릿 식사  (0) 2021.02.16
[BOJ]2621. 카드게임  (0) 2021.02.09
[BOJ]2061. 좋은 암호  (0) 2021.02.04
728x90
반응형

문제:

학교 근처 편의점에 새 초콜릿이 들어왔다. 이 초콜릿은 막대 모양이고, 각 막대는 정사각형 N개로 이루어져 있다. 초콜릿의 크기(정사각형의 개수)는 항상 2의 제곱 형태이다. 즉, 1, 2, 4, 8, 16, ...개의 정사각형으로 이루어져 있다.

상근이는 점심식사로 초콜릿을 먹는다. 이때, 적어도 K개 정사각형을 먹어야 남은 수업을 졸지 않고 버틸 수 있다. 상근이의 친구 선영이도 초콜릿을 좋아한다. 선영이는 초콜릿은 돈을 주고 사기 아깝다고 생각하기 때문에, 상근이가 주는 초콜릿만 먹는다.

상근이는 막대 초콜릿를 하나 산 다음에, 정확하게 K개 정사각형이 되도록 초콜릿을 쪼갠다. K개는 자신이 먹고 남는 것은 선영이에게 준다.

막대 초콜릿은 나누기 조금 어렵게 되어 있어서, 항상 가운데로만 쪼개진다. 즉, 정사각형이 D개 있는 막대는 D/2개 막대 두 조각으로 쪼개진다.

K개 정사각형을 만들기 위해서, 최소 몇 번 초콜릿을 쪼개야 하는지와 사야하는 가장 작은 초콜릿의 크기를 구하는 프로그램을 작성하시오. 상근이는 초콜릿을 하나만 살 수 있다. 꼭 한 조각이 K개일 필요는 없고, 여러 조각에 있는 정사각형을 합쳤을 때 K개이면 된다.

입력:

첫째 줄에 K가 주어진다. (1 ≤ K ≤ 1,000,000)

출력:

첫째 줄에는 상근이가 구매해야하는 가장 작은 초콜릿의 크기와 최소 몇 번 쪼개야 하는지를 출력한다.

풀이방법:

그리디한 방법을 사용해서 풀어야 하는 문제다.

1부터 2배씩 곱해나가면서 사야하는 가장 작은 초콜릿을 구매를 한 후, 그 초콜릿으로 부터 반으로 쪼개면서 답을 구한다.

반으로 쪼갠 후에 원하는 초콜릿 크기보다 작다면 그 크기만큼 빼주고 count를 하나 늘리고, 아직 크다면 다시 반으로 쪼개는 작업을 반복한다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
n=int(input())
size = 1
max_len = 0
answer = 0
 
while size < n:
    size *=2
    max_len = size
 
while n>0:
    if n>=size:
        n-=size
    else:
        size/=2
        answer+=1
 
print(max_len,answer)
cs

문제링크:

www.acmicpc.net/problem/2885

 

2885번: 초콜릿 식사

학교 근처 편의점에 새 초콜릿이 들어왔다. 이 초콜릿은 막대 모양이고, 각 막대는 정사각형 N개로 이루어져 있다. 초콜릿의 크기(정사각형의 개수)는 항상 2의 제곱 형태이다. 즉, 1, 2, 4, 8, 16, ...

www.acmicpc.net

 

728x90
반응형

'Algorithm > Python' 카테고리의 다른 글

[BOJ]10819. 차이를 최대로  (0) 2021.02.25
[BOJ]14888. 연산자 끼워넣기  (0) 2021.02.23
[BOJ]2621. 카드게임  (0) 2021.02.09
[BOJ]2061. 좋은 암호  (0) 2021.02.04
[BOJ]1251. 단어 나누기  (0) 2021.02.02

+ Recent posts