문제:

Day of Mourning의 기타리스트 강토가 사용하는 기타에서 N개의 줄이 끊어졌다. 따라서 새로운 줄을 사거나 교체해야 한다. 강토는 되도록이면 돈을 적게 쓰려고 한다. 6줄 패키지를 살 수도 있고, 1개 또는 그 이상의 줄을 낱개로 살 수도 있다.

끊어진 기타줄의 개수 N과 기타줄 브랜드 M개가 주어지고, 각각의 브랜드에서 파는 기타줄 6개가 들어있는 패키지의 가격, 낱개로 살 때의  가격이 주어질 때, 적어도 N개를 사기 위해 필요한 돈의 수를 최소로 하는 프로그램을 작성하시오.

입력:

첫째 줄에 N과 M이 주어진다. N은 100보다 작거나 같은 자연수이고, M은 50보다 작거나 같은 자연수이다. 둘째 줄부터 M개의 줄에는 각 브랜드의 패키지 가격과 낱개의 가격이 공백으로 구분하여 주어진다. 가격은 0보다 크거나 같고, 1,000보다 작거나 같은 정수이다.

출력:

첫째 줄에 기타줄을 적어도 N개 사기 위해 필요한 돈의 최솟값을 출력한다.

풀이방법:

여러 개의 기타줄에서 패키지 가격이 가장 작은 값과, 낱개 가격이 가장 작은 값만 필요하다. 이 두 개의 가격을 비교했을 때, 만약 낱개로 6개를 사는 것이 패키지 가격보다 싸다면 모든 기타줄을 낱개로 사는 것이 이득이다.

만약 그렇지 않다면 사야하는 기타줄을 6으로 나눴을 때 그 몫만큼은 패키지로 사는 것이 이득이다. 그 뒤로는 남은 나머지를 낱개로 샀을 때와 패키지로 샀을 때(적어도 N개를 구매하면 되므로 초과해서 사도 괜찮다.) 어떤 것이 이득인지 알아보고 그에 맞게 구매를 해야 한다. (ex 패키지 7 낱개 2면 패키지가 더 이득)  

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
n,m=map(int,input().split())
packages,single=[],[]
for i in range(m):
    p,s=map(int,input().split())
    packages.append(p)
    single.append(s)
minP,minS=min(packages),min(single)
if minP > minS*6:
    print(minS*n)
else:
    p,r=divmod(n,6)
    if minP > minS*r:
        print(minP*p+minS*r)
    else:
        print(minP*(p+1))
cs

문제링크:

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

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

[BOJ]7569. 토마토  (0) 2019.10.30
[BOJ]7576. 토마토  (0) 2019.10.29
[BOJ]5567. 결혼식  (0) 2019.10.17
[BOJ]1159. 농구 경기  (1) 2019.10.16
[BOJ]1016. 제곱ㄴㄴ수  (0) 2019.10.15

문제:

어느 날, 미르코는 우연히 길거리에서 양수 N을 보았다. 미르코는 30이라는 수를 존경하기 때문에, 그는 길거리에서 찾은 수에 포함된 숫자들을 섞어 30의 배수가 되는 가장 큰 수를 만들고 싶어한다.

 

미르코를 도와 그가 만들고 싶어하는 수를 계산하는 프로그램을 작성하라.

 

입력:

N을 입력받는다. N은 최대 10^5개의 숫자로 구성되어 있으며, 0으로 시작하지 않는다.

 

출력:

미르코가 만들고 싶어하는 수가 존재한다면 그 수를 출력하라. 그 수가 존재하지 않는다면, -1을 출력하라.

 

풀이방법:

 30의 배수가 되기 위해서는 10의 배수의 특징과 3의 배수 특징을 모두 가지고 있어야 한다. 10의 배수가 되려면 자릿수의 맨 끝이 0이 되어야 한다. 3의 배수가 되려면 각 자리를 다 더했을 때 3의 배수가 되어야 한다. 따라서 숫자에 0이 존재하고 각 자리를 모두 합했을 때 3의 배수라면 30의 배수를 만들 수 있다.

 따라서 30의 배수중 가장 큰 수를 원하기 때문에 각 자리를 리스트의 원소로 가지고 있는 배열을 역순으로(내림차순으로) 정렬한 뒤에 붙이는 것이 가장 큰 값이 될 것이다.

1
2
3
4
5
6
7
8
9
number=list(map(int,list(input())))
answer=-1
if 0 in number:
    if sum(number)%3 == 0:
        number.sort(reverse=True)
        answer=''
        for i in number:
            answer+=str(i)
print(answer)
cs

문제링크:

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

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

[BOJ]1561. 놀이공원  (0) 2019.09.20
[BOJ]1080. 행렬  (0) 2019.09.19
[BOJ]2875. 대회 or 인턴  (0) 2019.09.17
[BOJ]1744. 수 묶기  (0) 2019.09.16
[BOJ]14501. 퇴사  (0) 2019.09.11

문제:

백준대학교에는 대회에 나갈 때 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

+ Recent posts