문제:

백준이는 방 청소를 하면서 필요 없는 전공 서적을 사람들에게 나눠주려고 한다. 나눠줄 책을 모아보니 총 N권이었다. 책이 너무 많기 때문에 백준이는 책을 구분하기 위해 각각 1부터 N까지의 정수 번호를 중복되지 않게 매겨 두었다.

조사를 해 보니 책을 원하는 서강대학교 학부생이 총 M명이었다. 백준이는 이 M명에게 신청서에 두 정수 a, b (1 ≤ a ≤ b ≤ N)를 적어 내라고 했다. 그러면 백준이는 책 번호가 a 이상 b 이하인 책 중 남아있는 책 한 권을 골라 그 학생에게 준다. 만약 a번부터 b번까지의 모든 책을 이미 다른 학생에게 주고 없다면 그 학생에게는 책을 주지 않는다.

백준이가 책을 줄 수 있는 최대 학생 수를 구하시오.

입력:

첫째 줄에 테스트 케이스의 수가 주어진다.

각 케이스의 첫 줄에 정수 N(1 ≤ N ≤ 1,000)과 M(1 ≤ M ≤ 1,000)이 주어진다. 다음 줄부터 M개의 줄에는 각각 정수 ai, bi가 주어진다. (1 ≤ ai ≤ bi ≤ N)

출력:

각 테스트 케이스마다 백준이가 책을 줄 수 있는 최대 학생 수를 한 줄에 하나씩 출력한다.

풀이방법:

 greedy하게 문제를 풀어주도록 한다. 다만, greedy한 조건 내에 범위가 짧은(a와 b의 차가 작은) 것 부터 먼저 배치하도록 한다. (1,3), (1,2), (1,2) 의 경우 모두에게 책을 줄 수 있지만 추가 조건이 없다면 답이 2로 나올 수 있다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
from collections import deque
 
test_case = int(input())
 
for tc in range(test_case):
    N, M = map(int, input().split())
    visited=[0]*(N+1)
    list_ = []
    for _ in range(M):
        a,b = map(int,input().split())
        list_.append((a,b))
    list_ = sorted(list_, key=lambda x: x[1])
    answer = 0
    for a, b in list_:
        for i in range(a,b+1):
            if not visited[i]:
                answer+=1
                visited[i] = 1
                break
    print(answer)
cs

문제링크:

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

 

9576번: 책 나눠주기

백준이는 방 청소를 하면서 필요 없는 전공 서적을 사람들에게 나눠주려고 한다. 나눠줄 책을 모아보니 총 N권이었다. 책이 너무 많기 때문에 백준이는 책을 구분하기 위해 각각 1부터 N까지의

www.acmicpc.net

 

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

[BOJ]10827. a^b  (0) 2022.02.09
[BOJ]2631. 줄세우기  (0) 2022.02.08
[BOJ]21610. 마법사 상어와 비바라기  (0) 2021.11.05
[BOJ]20057. 마법사 상어와 토네이도  (0) 2021.11.04
[BOJ] 15685. 드래곤 커브  (0) 2021.11.03

문제:

주사위는 위와 같이 생겼다. 주사위의 여섯 면에는 수가 쓰여 있다. 위의 전개도를 수가 밖으로 나오게 접는다.

A, B, C, D, E, F에 쓰여 있는 수가 주어진다.

지민이는 현재 동일한 주사위를 N^3개 가지고 있다. 이 주사위를 적절히 회전시키고 쌓아서, N*N*N크기의 정육면체를 만들려고 한다. 이 정육면체는 탁자위에 있으므로, 5개의 면만 보인다.

N과 주사위에 쓰여 있는 수가 주어질 때, 보이는 5개의 면에 쓰여 있는 수의 합의 최솟값을 출력하는 프로그램을 작성하시오.

입력:

첫째 줄에 N이 주어진다. 둘째 줄에 주사위에 쓰여 있는 수가 주어진다. 위의 그림에서 A, B, C, D, E, F에 쓰여 있는 수가 차례대로 주어진다. N은 1,000,000보다 작거나 같은 자연수이고, 쓰여 있는 수는 50보다 작거나 같은 자연수이다.

출력:

첫째 줄에 문제의 정답을 출력한다.

풀이방법:

 주사위를 쌓아서 N*N*N 크기의 정육면체를 만들게 되면, 밖으로 노출되는 면이 가장 많은 경우는 3개인 면인 경우이다. 정육면체에서 3개의 면 주사위의 개수, 2개의 면 주사위의 개수, 1개의 면 주사위의 개수는 N에 따라서 달라지게 된다.

 

1. 3개의 면 주사위의 개수는 항상 위쪽 면의 꼭짓점에서만 나타나므로 N과 상관없이 4번만 등장하게 된다.

2. 2개의 면이 나타나는 주사위의 개수는 모서리에서만 나타나게 된다. 이 때 위쪽 면에서는 꼭짓점에서 이미 사용한 주사위가 있으므로 이를 제외해주고 계산해줘야 한다. 따라서 (N-1)*4+(N-2)*4개가 존재한다.

3. 1개의 면이 나타나는 주사위는 ((N-2)^2)*5+(N-2)*4 개 있다.

 

 주사위는 위 그림에서 나타나는 것처럼 전개도를 따라서 접게 되므로, 모든 숫자 중에서 가장 작은 3개(혹은 2개)를 골라서 최솟값을 구하면 안된다. A에 있는 숫자는 F와 만날 수 없기 때문이다. 따라서 나타날 수 있는 3개인 경우는 [(0,1,2),(0,1,3),(0,2,4),(0,3,4),(1,2,5),(1,3,5),(2,4,5),(3,4,5)]와 같기 때문에 이 중에서 가장 작은 값을 가지는 경우를 찾도록 하고, 2개인 경우는 서로 반대 면에 있는 숫자만 피하면 되므로, 이를 제외하고 계산하도록 한다.

 N이 1인 경우는 위에서 구한 케이스 구분이 필요없기 때문에 따로 처리하도록 한다.

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
import copy
 
def threemin(numbers):
    candidate = [(0,1,2),(0,1,3),(0,2,4),(0,3,4),(1,2,5),(1,3,5),(2,4,5),(3,4,5)]
    answer = sum(numbers)
    for c in candidate:
        temp = 0
        for idx in c:
            temp +=numbers[idx]
        answer = min(answer,temp)
    return answer
 
def twomin(numbers):
    answer = sum(numbers)
    for i in range(len(numbers)):
        for j in range(i+1,len(numbers)):
            temp = 0
            if i+j==5:
                continue
            else:
                temp += (numbers[i]+numbers[j])
                answer = min(temp,answer)
    return answer
        
 
= int(input())
numbers = list(map(int,input().split()))
 
answer = 0
if N==1:
    answer = sum(numbers)-max(numbers)
else:
    three = threemin(numbers)
    two = twomin(numbers)
    answer += three*4
    answer += two*(N-1)*4+two*(N-2)*4
    answer += min(numbers)*(N-2)*(N-2)*5+min(numbers)*(N-2)*4
print(answer)
cs

문제링크:

www.acmicpc.net/problem/1041

 

1041번: 주사위

첫째 줄에 N이 주어진다. 둘째 줄에 주사위에 쓰여 있는 수가 주어진다. 위의 그림에서 A, B, C, D, E, F에 쓰여 있는 수가 차례대로 주어진다. N은 1,000,000보다 작거나 같은 자연수이고, 쓰여 있는 수

www.acmicpc.net

 

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

[BOJ]7562. 나이트의 이동  (0) 2020.11.19
[BOJ]1992. 쿼드트리  (0) 2020.11.17
[BOJ]1059. 수2  (0) 2020.11.10
[BOJ]10775. 공항  (0) 2020.10.29
[BOJ]1786. 찾기  (0) 2020.10.27

문제:

어떤 나라에 N개의 도시가 있다. 이 도시들은 일직선 도로 위에 있다. 편의상 일직선을 수평 방향으로 두자. 제일 왼쪽의 도시에서 제일 오른쪽의 도시로 자동차를 이용하여 이동하려고 한다. 인접한 두 도시 사이의 도로들은 서로 길이가 다를 수 있다. 도로 길이의 단위는 km를 사용한다.

 

처음 출발할 때 자동차에는 기름이 없어서 주유소에서 기름을 넣고 출발하여야 한다. 기름통의 크기는 무제한이어서 얼마든지 많은 기름을 넣을 수 있다. 도로를 이용하여 이동할 때 1km마다 1리터의 기름을 사용한다. 각 도시에는 단 하나의 주유소가 있으며, 도시 마다 주유소의 리터당 가격은 다를 수 있다. 가격의 단위는 원을 사용한다.

 

예를 들어, 이 나라에 다음 그림처럼 4개의 도시가 있다고 하자. 원 안에 있는 숫자는 그 도시에 있는 주유소의 리터당 가격이다. 도로 위에 있는 숫자는 도로의 길이를 표시한 것이다.

제일 왼쪽 도시에서 6리터의 기름을 넣고 더 이상의 주유 없이 제일 오른쪽 도시까지 이동하면 총 비용은 30원이다. 만약 제일 왼쪽 도시에서 2리터의 기름을 넣고(2x5 = 10원) 다음 번 도시까지 이동한 후 3리터의 기름을 넣고 (3x2 = 6원) 다음 도시에서 1리터의 기름을 넣어(1x4 = 4원) 제일 오른쪽 도시로 이동하면, 총 비용은 20원이다.

또 다른 방법으로 제일 왼쪽 도시에서 2리터의 기름을 넣고(2x5 = 10원) 다음 번 도시까지 이동한 후 4리터의 기름을 넣고(4x2 = 8원) 제일 오른쪽 도시까지 이동하면, 총 비용은 18원이다.

 

각 도시에 있는 주유소의 기름 가격과, 각 도시를 연결하는 도로의 길이를 입력으로 받아 제일 왼쪽 도시에서 제일 오른쪽 도시로 이동하는 최소의 비용을 계산하는 프로그램을 작성하시오.

입력:

표준 입력으로 다음 정보가 주어진다. 첫 번째 줄에는 도시의 개수를 나타내는 정수 N(2<=N<=100.000)이 주어진다. 다음 줄에는 인접한 두 도시를 연결하는 도로의 길이가 제일 왼쪽 도로부터 N-1개의 자연수로 주어진다. 다음 줄에는 주유소의 리터당 가격이 제일 왼쪽 도시부터 순서대로 N개의 자연수로 주어진다. 제일 왼쪽 도시부터 제일 오른쪽 도시까지의 거리는 1이상 1,000,000,000 이하의 자연수이다. 리터당 가격은 1 이상 1,000,000,000 이하의 자연수이다.

출력:

표준 출력으로 제일 왼쪽 도시에서 제일 오른쪽 도시로 가는 최소 비용을 출력한다.

풀이방법:

제일 적은 비용을 지불하기 위해서는 제일 가격이 낮은 주유소에서 남은 거리에 해당하는 기름을 다 넣어야 한다.

하지만 왼쪽에서 오른쪽으로 순차적으로 진행이 되는 것이으므로 지금까지 이동한 곳에서 가장 낮은 가격의 주유소의 기름을 넣어야 한다. 예시로 보면 다음과 같다.

 

- 첫 도시의 주유소에서 가격이 5이고 다른 선택지가 없고 다음 도시까지는 2km를 가야하기 때문에 10원(2x5)을 지불한다. (minP =5)

 

- 두번째 도시에 도착해서 가격을 보니 2원이다. 따라서 minP를 2로 바꾸고 다음 주유소까지 가기 위해 6원(3x2)을 지불한다.(minP=2)

 

- 세번째 도시의 가격은 4원이다. 따라서 두번째 도시에서 미리 기름을 더 넣어두고 오는 것이 이득이였기 때문에 마지막 도시까지 이동하는 것도 두번째 도시에서 넣고 와야 한다. 따라서 2원(1x2)을 추가 지불한다.

 

따라서 최저 비용은 18원이 된다.

 

이를 반복문 하나로 표현하였고, 인덱스를 편하게 맞춰주기 위해서 간격배열에 0을 임의로 추가하였다.(답에 영향을 주진 않는다.)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
n=int(input())
d=[0]*100000
dist = list(map(int,input().split()))
dist.append(0)
price = list(map(int,input().split()))
 
d[0= price[0]*dist[0]
minP=price[0]
for i in range(1,n):
    if price[i] < minP:
        minP = price[i]
   d[i] = d[i-1+ minP*dist[i]
    
print(d[n-1])
cs

 

문제링크:

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

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

[BOJ]6588. 골드바흐의 추측  (0) 2020.03.03
[Programmers]2019 Kakao.길 찾기 게임  (0) 2020.02.27
[BOJ]2485. 가로수  (0) 2020.02.20
[BOJ]1182. 부분수열의 합  (0) 2020.02.18
[BOJ]1431. 시리얼 번호  (1) 2020.02.13

문제:

0과 1로만 이루어진 행렬 A와 행렬 B가 있다. 이때, 행렬 A를 행렬 B로 바꾸는데 필요한 연산의 횟수의 최솟값을 구하는 프로그램을 작성하시오.

 

행렬을 변환하는 연산은 어떤 3*3크기의 부분 행렬에 있는 모든 원소를 뒤집는 것이다. (0 -> 1,1 -> 0)

입력:

첫째 줄에 행렬의 크기 N M이 주어진다. N과 M은 50보다 작거나 같은 자연수이다. 둘째 줄부터 N개의 줄에는 행렬 A가 주어지고, 그 다음줄부터 N개의 줄에는 행렬 B가 주어진다.

 

출력:

첫째 줄에 문제의 정답을 출력한다. 만약 A를 B로 바꿀 수 없다면 -1을 출력한다.

 

풀이방법:

 그리디 방법이므로 현재 위치하고 있는 곳에서 A와 B를 비교해서 뒤집을지 결정해주면 된다. 왼쪽 위부터 오른쪽으로 한칸씩 미끄러져 가며 비교를 하고 맨 윗줄을 다 비교하면 그 아랫줄로 내려가서 비교를 해주도록 한다. 이렇게 하면 한 번 그 위치를 기준으로 뒤집은 경우에는 다시 그 칸을 뒤집진 않기 때문에 한 번 뒤집었던 부분을 다시 뒤집을 수 있다는 걱정을 할 필요 없다. 따라서 이렇게 행렬A를 탐색하며 다 뒤집은 다음에 행렬 B와 비교해서 일치한다면 연산의 최솟값을 출력하고 그렇지 않다면 -1을 출력하도록 하였다.

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
def change(x,y,A):
    for i in range(3):
        for j in range(3):
            if A[x+i][y+j]==0:
                A[x+i][y+j]=1
            else:
                A[x+i][y+j]=0
    return A
n,m = map(int,input().split())
A=[]
B=[]
for i in range(n):
    A.append(list(map(int,list(input()))))
for i in range(n):
    B.append(list(map(int,list(input()))))
 
count=0
for i in range(n-3+1):
    for j in range(m-3+1):
        if A[i][j]!=B[i][j]:
            A=change(i,j,A)
            count+=1
answer=True
for i in range(n):
    for j in range(m):
        if A[i][j]!=B[i][j]:
            answer=False
if answer:
    print(count)
else:
    print(-1)
cs

문제 링크:

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

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

[BOJ]2022. 사다리  (0) 2019.09.21
[BOJ]1561. 놀이공원  (0) 2019.09.20
[BOJ]10610. 30  (0) 2019.09.18
[BOJ]2875. 대회 or 인턴  (0) 2019.09.17
[BOJ]1744. 수 묶기  (0) 2019.09.16

문제:

백준대학교에는 대회에 나갈 때 2명의 여학생과 1명의 남학생이 팀을 결성해서 나가는 것이 원칙이다.(왜인지는 총장님께 여쭈어보는 것이 좋겠다.)

백준대학교는 뛰어난 인재들이 많아 올해에도 N명의 여학생과 M명의 남학생이 팀원을 찾고 있다.

그런데 올해에는 대회에 참여하라는 학생들 중 K명을 반드시 인턴쉽 프로그램에 참여하라는 학교의 방침이 생기게 되었다. 인턴쉽에 참여하는 학생은 대회에 참여하지 못한다.

입력:

첫째 줄에 N,M,K가 순서대로 주어진다 (0<=M<=100),(0<=N<=100),()<=K<=M+N)

 

출력:

만들 수 있는 팀의 최댓값을 출력하면 된다.

 

풀이 방법:

 인턴쉽에 K명이 반드시 참가해야하므로 이 인원을 먼저 빼도록 한다. 따라서 현재 남자와 여자 인원이 있을 때 만들 수 있는 팀이 있을 때 남는 인원들을 한명씩 인턴쉽으로 빼도록 한다. 이렇게 모두 인턴쉽에 K명을 모두 배정하고 난 뒤에 남은 사람들로 팀의 수를 출력하도록 한다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
n,m,k=map(int,input().split())
 
while k > 0:
    if n//2 >=m:
        n-=1
    else:
        m-=1
    k-=1
    
if n//2 >=m:
    answer=m
else:
    answer=n//2
print(answer)
cs

문제 링크:

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

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

[BOJ]1080. 행렬  (0) 2019.09.19
[BOJ]10610. 30  (0) 2019.09.18
[BOJ]1744. 수 묶기  (0) 2019.09.16
[BOJ]14501. 퇴사  (0) 2019.09.11
[BOJ]1371. 가장 많은 글자  (0) 2019.09.10

문제:

길이가 N인 수열이 주어졌을 때, 그 수열의 합을 구하려고 한다. 하지만, 그냥 그 수열의 합을 모두 더해서 구하는 것이 아니라, 수열의 두 수를 묶으려고 한다. 어떤 수를 묶으려고 할 때, 위치에 상관없이 묶을 수 있다. 하지만, 같은 위치에 있는 수(자기 자신)을 묶는 것은 불가능하다. 그리고 어떤 수를 묶게 되면, 수열의 합을 구할 때 묶은 수는 서로 곱한 후에 더한다.

 

예를 들면, 어떤 수열이 {0,1,2,4,3,5}일 때, 그냥 이 수열의 합을 구하면 0+1+2+4+3+5 =15이다. 하지만, 2와 3을 묶고, 4와 5를 묶게 되면, 0+1+(2*3)+(4*5) = 27이 되어 최대가 된다.

 

수열의 모든 수는 단 한번만 묶거나, 아니면 묶지 않아야 한다.

 

수열이 주어졌을 때, 수열의 각 수를 적절히 묶었을 때, 그 합이 최대가 되게 하는 프로그램을 작성하시오.

 

입력:

첫째 줄에 수열의 크기 N이 주어진다. N은 10,000보다 작다. 둘째 줄부터 N개의 줄에, 수열에 각 수가 주어진다. 수열의 수는 -10,000보다 크거나 같고, 10,000보다 작거나 같은 정수이다.

 

출력:

수를 적절히 묶어 그 합이 최댓값을 출력한다. 정답은 항상 2^31보다 작다.

풀이 방법:

 합이 최댓값이 되도록 만들기 위해서는 양수는 양수끼리 곱해야 하고, 음수는 음수와 곱해서 양수가 되도록 만들어야 한다. 또한 작은 수와 곱하기 보다는 절대값이 큰 값들끼리 묶어야 합이 최댓값이 될 것이다. 따라서 수를 받을 때 양수와 음수로 나누어서 받도록 한다.

 그리고 값 중에서 1과 0은 최댓값으로 만들 때 방해가 되는 항목들이다. 0과 함께 묶으면 그 값은 0이 되어버려 사용할 수 없게 된다. 따라서 이는 음수가 홀수일 때 사용하도록 한다. 또한 1도 양수와 곱해졌을 때 손해가 되는 항목이다. (4*1<4+1) 묶지 않고 그냥 더하는 것이 크기 때문이다. 그래서 이 둘의 항목은 따로 셈을 해주도록 한다,

 양수와 음수로 분리를 하고 난 뒤에 음수는 오름차순, 양수는 내림차순으로 정렬해서 곱을 편하게 만들었다. 또한 이들의 개수가 홀수이면 예외처리를 따로 해줘야 하는 번거로움이 생기기 때문에 임의의 값인 1이나 0을 넣어주도록 했다. 

 이러한 사전작업이 끝난다면 두 값씩 묶은 뒤에 더해주도록 했다.

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
plus=[]
minus=[]
one=0
zero=0
for i in range(int(input())):
    n=int(input())
    if n==1:
        one+=1
    elif n==0:
        zero+=1  
    elif n<0:
        minus.append(n)
    else:
        plus.append(n)
minus.sort()
plus.sort(reverse=True)
if len(plus)%2==1:
    plus.append(1)
if len(minus)%2==1:
    if zero > 0:
        minus.append(0)
    else:
        minus.append(1)
answer=one
for i in range(0,len(plus),2):
    answer+=plus[i]*plus[i+1]
for i in range(0,len(minus),2):
    answer+=minus[i]*minus[i+1]
    
print(answer)
cs

문제 링크:

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

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

[BOJ]10610. 30  (0) 2019.09.18
[BOJ]2875. 대회 or 인턴  (0) 2019.09.17
[BOJ]14501. 퇴사  (0) 2019.09.11
[BOJ]1371. 가장 많은 글자  (0) 2019.09.10
[BOJ]9933. 민균이의 비밀번호  (0) 2019.09.09

문제:

N(1<=N<=100,000)개의 로프가 있다. 이 로프를 이용하여 이런 저런 물체를 들어올릴 수 있다. 각각의 로프는 그 굵기나 길이가 다르기 때문에 들 수 있는 물체의 중량이 서로 다를 수도 있다. 

하지만 여러 개의 로프를 병렬로 연결하면 각각의 로프에 걸리는 중량을 나눌 수 있다. k개의 로프를 사용하여 중량이 w인 물체를 들어올릴 때, 각각의 로프에는 모두 고르게 w/k만큼의 중량이 걸리게 된다.

각 로프들에 대한 정보가 주어졌을 때, 이 로프들을 이용하여 들어올릴 수 있는 물체의 최대 중량을 구해내는 프로그램을 작성하시오. 모든 로프를 사용해야 할 필요는 없으며, 임의로 몇 개의 로프를 골라서 사용해도 된다. 단, 각각의 로프는 한 개씩만 존재한다.

입력:

첫째 줄에 정수 N이 주어진다. 다음 N개의 줄에는 각 로프가 버틸 수 있는 최대 중량이 주어진다. 이 값은 10,000을 넘지 않는 정수이다.

출력:

첫째 줄에 답을 출력 한다.

풀이 방법:

로프가 중량을 견딜 수 있어야 하므로 로프들 중에 가장 작은 중량을 버틸 수 있는 것에 기준을 맞춰줘야 한다. 따라서 로프의 중량을 모두 받아서 내림차순으로 정렬을 하고 난 뒤에 하나씩 count를 늘려가면서 그 중 작은 로프의 중량과 count를 곱해서 버틸 수 있는 물체의 무게를 구하도록 했다.

1
2
3
4
5
6
7
8
9
10
n=int(input())
rope=[]
for i in range(n):
    rope.append(int(input()))
rope=sorted(rope,reverse=True)
answer=0
for i in range(n):
    if answer < rope[i]*(i+1):
        answer=rope[i]*(i+1)
print(answer)
cs


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

[BOJ]4949. 균형잡힌 세상  (0) 2019.07.17
[BOJ]2004. 조합 0의 개수  (0) 2019.07.16
[BOJ]11047. 동전0  (0) 2019.07.14
[BOJ]1931. 회의실배정  (0) 2019.07.13
[BOJ]1712. 손익분기점  (0) 2019.07.12

문제:

준규가 가지고 있는 동전은 총 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원은 존재하기 때문에 (A1=1) 항상 값을 구할 수 있다. 따라서 이 문제는 그리디 알고리즘으로 큰 동전부터 값을 넣어주면 된다. 처음에는 뺄 수 있을 때마다 한 번씩 빼면서 count를 하나씩 증가시켰는데 시간초과가 발생하였다.
 따라서 이를 해결하고자 처음에 동전의 가치를 받을 때에도 K를 넘는 동전의 가치는 받지 않았고, k를 동전의 가치로 나눈 몫을 구해서 count에 더하도록 하였더니 시간초과를 피해서 통과 할 수 있었다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
n,k = map(int,input().split())
coins=[]
answer=0
for i in range(n):
    coin=int(input())
    if coin <= k:
        coins.append(coin)
coins.reverse()
while k != 0:
    if k//coins[0]>0:
        answer+=k//coins[0]
        k-=(k//coins[0])*coins[0]
    else:
        coins.pop(0)
print(answer)
cs


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

[BOJ]2004. 조합 0의 개수  (0) 2019.07.16
[BOJ]2217. 로프  (0) 2019.07.15
[BOJ]1931. 회의실배정  (0) 2019.07.13
[BOJ]1712. 손익분기점  (0) 2019.07.12
[BOJ]3053. 택시 기하학  (1) 2019.07.11

문제:

한 개의 회의실이 있는데 이를 사용하고자 하는 N개의 회의들에 대하여 회의실 사용표를 만들려고 한다. 각 회의 I에 대해 시작시간과 끝나는 시간이 주어져 있고, 각 회의가 겹치지 않게 하면서 회의실을 사용할 수 있는 최대수의 회의를 찾아라. 단, 회의는 한번 시작하면 중간에 중단될 수 없으며 한 회의가 끝나는 것과 동시에 다음 회의가 시작될 수 있다. 회의의 시작시간과 끝나는 시간이 같을 수도 있다. 이 경우에는 시작하자마자 끝나는 것으로 생각하면 된다.

입력:

첫째 줄에 회의의 수 N(1<=N<=100,000)이 주어진다. 둘째 줄부터 N+1 줄까지 각 회의의 정보가 주어지는데 이것은 공백을 사이에 두고 회의의 시작시간과 끝나는 시간이 주어진다. 시작 시간과 끝나는 시간은 2^31 -1보다 작거나 같은 자연수 또는 0이다.

출력:

첫째 줄에 최대 사용할 수 있는 회의 수를 출력하여라.

풀이 방법:

 그리디 알고리즘을 사용해서 풀어야 하는 문제라고 해서 어떻게 최적값만을 고를지 생각하다가 우선적으로 생각난 것이 시작 시간과 끝 시간의 차이가 작은 순으로 정렬해서 찾아보자고 생각했다. 어느정도 구현이 될 것 같긴 했지만 너무 복잡할 것 같아서 다른 방법을 생각하고자 했다.
 그래서 단순하게 끝나는 시간이 작은 순으로 정렬을 하고 먼저 나오는 회의실부터 우선 배정하도록 하게 하고 배정된 끝시간보다 초과된 시작시간을 만나면 회의실을 바꾸도록 한다. (같아도 된다.)

1
2
3
4
5
6
7
8
9
10
11
12
13
meeting=[]
for i in range(int(input())):
    n,m=map(int,input().split())
    meeting.append((n,m))
meeting.sort(key=lambda x : x[0])
meeting.sort(key=lambda x : x[1])
count=1
end=meeting[0][1]
for i in range(1,len(meeting)):
    if meeting[i][0>= end:
        count+=1
        end=meeting[i][1]
print(count)
cs


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

[BOJ]2217. 로프  (0) 2019.07.15
[BOJ]11047. 동전0  (0) 2019.07.14
[BOJ]1712. 손익분기점  (0) 2019.07.12
[BOJ]3053. 택시 기하학  (1) 2019.07.11
[BOJ]1904. 01타일  (0) 2019.07.10

문제:

n개의 섬 사이에 다리를 건설하는 비용(costs)이 주어질 때, 최소의 비용으로 모든 섬이 서로 통행 가능하도록 만들 때 필요한 최소 비용을 return 하도록 solution을 완성하세요.

다리를 여러 번 건너더라도, 도달할 수만 있으면 통행가능하다고 봅니다. 예를 들어 A 섬과 B 섬 사이에 다리가 있고, B 섬과 C 섬 사이에 다리가 있으면 A 섬과 C 섬은 서로 통행 가능합니다.


문제 풀이:

전형적인 Kruskal 알고리즘을 사용해서 푸는 문제이다. Kruskal 알고리즘이란, 탐욕적인 방법을 이용하여 그래프의 모든 정점을 최소 비용으로 연결하는 방법이다. Kruskal 알고리즘을 사용하는 방법은 간단하다. 처음 시작하는 노드로 부터 하나의 간선을 선택해가면 된다. 

이 문제의 예시로 설명을 들면 처음에 0에서 시작을 한다고 가정을 하자. 

1. 0에 연결되어 있는 간선은 0-1(1), 0-2(2) 두 가지 간선이 있다. 최소 비용으로 연결하는 것이 목적이므로 0-1 간선을 선택하고 1의 노드를 연결된 노드 집합에 넣도록 한다. 

2. 0과 1의 노드에 연결되어 있는 간선을 찾도록 하자. 그러면 0-2 (2), 1-2(5), 1-3(1) 세 가지 간선이 존재하게 되고, 역시 최소를 선택하므로 1-3을 선택하게 된다.

3. 위와 같은 방법으로 진행을 하면 0-2 간선을 선택하게 되어 모든 노드들이 연결되게 된다.

이제 이 방법들을 코드로 옮기면 다음과 같다. connect라는 연결된 노드 집합을 만들고 이 값이 n과 같게 되면 while이 끝나도록 한다. costs를 반복하여 connect에 있는 노드들의 간선을 찾도록 한다. (단 시점과 종점이 모두 connect에 있으면 안된다.) 이 간선들의 최소값을 찾아 answer에 더하고 connect 집합에 노드를 추가시키고 costs에서는 간선을 빼도록 한다. 이 작업을 모든 노드가 connect에 들어갈 때까지 반복한 answer를 반환하면 된다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
def solution(n, costs):
    costs.sort()
    connect=[costs[0][0]]
    answer = 0
    while len(connect)!=n:
        temp=1000000000000000
        idx=0
        for i in range(len(costs)):
            if costs[i][0in connect or costs[i][1in connect:
                if costs[i][0in connect and costs[i][1in connect:
                    continue
                if temp > costs[i][2]:
                    temp=costs[i][2]
                    idx=i
        answer+=temp
        connect.append(costs[idx][0])
        connect.append(costs[idx][1])
        connect=list(set(connect))
        costs.pop(idx)
    return answer
cs


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

[BOJ]1904. 01타일  (0) 2019.07.10
[Programmers]Lv 3. 기지국 설치  (0) 2019.07.09
[Programmers]Lv 3. 단속카메라  (2) 2019.07.07
[BOJ]2869. 달팽이는 올라가고 싶다.  (0) 2019.07.06
[BOJ]1011. Fly me to the Alpha Centauri  (0) 2019.07.05

+ Recent posts