문제 설명


점심시간에 도둑이 들어, 일부 학생이 체육복을 도난당했습니다. 다행히 여벌 체육복이 있는 학생이 이들에게 체육복을 빌려주려 합니다. 학생들의 번호는 체격 순으로 매겨져 있어, 바로 앞번호의 학생이나 바로 뒷번호의 학생에게만 체육복을 빌려줄 수 있습니다. 예를 들어, 4번 학생은 3번 학생이나 5번 학생에게만 체육복을 빌려줄 수 있습니다. 체육복이 없으면 수업을 들을 수 없기 때문에 체육복을 적절히 빌려 최대한 많은 학생이 체육수업을 들어야 합니다.

전체 학생의 수 n, 체육복을 도난당한 학생들의 번호가 담긴 배열 lost, 여벌의 체육복을 가져온 학생들의 번호가 담긴 배열 reserve가 매개변수로 주어질 때, 체육수업을 들을 수 있는 학생의 최댓값을 return 하도록 solution 함수를 작성해주세요.

 

제한조건

 

  • 전체 학생의 수는 2명 이상 30명 이하입니다.
  • 체육복을 도난당한 학생의 수는 1명 이상 n명 이하이고 중복되는 번호는 없습니다.
  • 여벌의 체육복을 가져온 학생의 수는 1명 이상 n명 이하이고 중복되는 번호는 없습니다.
  • 여벌 체육복이 있는 학생만 다른 학생에게 체육복을 빌려줄 수 있습니다.
  • 여벌 체육복을 가져온 학생이 체육복을 도난당했을 수 있습니다. 이때 이 학생은 체육복을 하나만 도난당했다고 가정하며, 남은 체육복이 하나이기에 다른 학생에게는 체육복을 빌려줄 수 없습니다.

 

입출력 예

 

n lost reserve return
5 [2, 4] [1, 3, 5] 5
5 [2, 4] [3] 4
3 [3] [1] 2

 

입출력 예 설명


예제 #1
1번 학생이 2번 학생에게 체육복을 빌려주고, 3번 학생이나 5번 학생이 4번 학생에게 체육복을 빌려주면 학생 5명이 체육수업을 들을 수 있습니다.

예제 #2
3번 학생이 2번 학생이나 4번 학생에게 체육복을 빌려주면 학생 4명이 체육수업을 들을 수 있습니다.

 

나의 풀이

 

def solution(n, lost, reserve):
    a = set(reserve)-set(lost)
    b = len(lost)
    if len(a) == len(reserve):
        c = 0
    else:
        c = len(reserve) - len(a)
        lost = set(lost) - (set(reserve) - set(a))
    
    for i in a:
        if len(lost) == 0:
            break
        
        if i - 1 in lost:
            c += 1
            lost.remove(i - 1)
        elif i + 1 in lost:
            c += 1
            lost.remove(i + 1)
            
    if n - b + c > n:
        return n
    else:
        return n - b + c

1. set을 통해 reverse와 lost의 차집합을 구해줍니다. (겹치는 숫자가 있는지 검사해서 a에 넣기)

2. reserve에서 lost에 겹치지 않는 것(a)을 비교하는데 바로 앞번호의 학생이나 바로 뒷번호의 학생에게만 체육복을 빌려줄 수 있기 때문에 앞번호나 뒷번호에 체육복을 잃어버렸으면 빌려준 학생수를 올려주고 잃어버린 항목에서 해당 학생을 지워줍니다.

3. 모든 학생이 체육복을 빌릴 수 있으면 전체 학생수 n을 출력하고 아니면 빌릴 수 있는 최대 학생수를 출력해줍니다.

 

다른 사람의 풀이

 

def solution(n, lost, reserve):
    _reserve = [r for r in reserve if r not in lost]
    _lost = [l for l in lost if l not in reserve]
    for r in _reserve:
        f = r - 1
        b = r + 1
        if f in _lost:
            _lost.remove(f)
        elif b in _lost:
            _lost.remove(b)
    return n - len(_lost)

리스트 _reserve와 _lost를 새로 만들어줍니다.
_reserve 요소의 앞번호나 뒷번호가 체육복을 잃어버렸으면 빌려준 학생수를 올려주고 잃어버린 항목에서 해당 학생을 지워줍니다.

전체 학생에서 체육복을 빌리지 못한 학생수를 빼서 출력해줍니다.

 


프로그래머스 '체육복' : programmers.co.kr/learn/courses/30/lessons/42862

 

코딩테스트 연습 - 체육복

점심시간에 도둑이 들어, 일부 학생이 체육복을 도난당했습니다. 다행히 여벌 체육복이 있는 학생이 이들에게 체육복을 빌려주려 합니다. 학생들의 번호는 체격 순으로 매겨져 있어, 바로 앞번�

programmers.co.kr

 

 

문제


스타박스는 손님을 입장시킬 때 독특한 방법으로 입장시킨다.

스타박스에서는 손님을 8시가 될 때 까지, 문앞에 줄 세워 놓는다. 그리고 8시가 되는 순간 손님들은 모두 입구에서 커피를 하나씩 받고, 자리로 간다. 강호는 입구에서 커피를 하나씩 주는 역할을 한다.

손님들은 입구에 들어갈 때, 강호에게 팁을 준다. 손님들은 자기가 커피를 몇 번째 받는지에 따라 팁을 다른 액수로 강호에게 준다. 각 손님은 강호에게 원래 주려고 생각했던 돈 - (받은 등수 - 1) 만큼의 팁을 강호에게 준다. 만약, 위의 식으로 나온 값이 음수라면, 강호는 팁을 받을 수 없다.

예를 들어, 민호는 팁을 3원 주려고 했고, 재필이는 팁을 2원, 주현이가 팁을 1원 주려고 한 경우를 생각해보자.

민호, 재필, 주현이 순서대로 줄을 서있다면, 민호는 강호에게 3-(1-1) = 3원, 재필이는 2-(2-1) = 1원, 주현이는 1-(3-1) = -1원을 팁으로 주게 된다. 주현이는 음수이기 때문에, 강호에게 팁을 주지 않는다. 따라서, 강호는 팁을 3+1+0=4원을 받게 된다.

스타박스 앞에 있는 사람의 수 N과, 각 사람이 주려고 생각하는 팁이 주어질 때, 손님의 순서를 적절히 바꿨을 때, 강호가 받을 수 잇는 팁의 최댓값을 구하는 프로그램을 작성하시오.

 

입력


첫째 줄에 스타박스 앞에 서 있는 사람의 수 N이 주어진다. N은 100,000보다 작은 자연수이다. 둘째 줄부터 총 N개의 줄에 각 사람이 주려고 하는 팁이 주어진다. 팁은 100,000보다 작거나 같은 자연수이다.

 

출력


강호가 받을 수 있는 팁의 최댓값을 출력한다.

 

예제 입력과 출력

 

 

알고리즘 분류


그리디 알고리즘

 

정답

 

import sys

n=int(sys.stdin.readline().strip())
a=[]
s=0

for i in range(n):
    a.append(int(sys.stdin.readline().strip()))

a.sort(reverse=True)

for i in range(n):
    b=a[i] - i

    if b > 0:
        s += b

print(s)

원래 주려고 생각했던 돈 - (받은 등수 - 1) 만큼의 팁을 주는데 원래 주려고 생각했던 돈이 큰 사람을 등수를 높게 해야 팁의 최댓값을 구할 수 있습니다.

 


백준 알고리즘 1758번 : www.acmicpc.net/problem/1758

 

1758번: 알바생 강호

첫째 줄에 스타박스 앞에 서 있는 사람의 수 N이 주어진다. N은 100,000보다 작은 자연수이다. 둘째 줄부터 총 N개의 줄에 각 사람이 주려고 하는 팁이 주어진다. 팁은 100,000보다 작거나 같은 자연수

www.acmicpc.net

 

문제


2007년 KOI에 N명의 학생들이 참가하였다. 경시일 전날인 예비소집일에, 모든 학생들은 자신이 N명 중에서 몇 등을 할 것인지 예상 등수를 적어서 제출하도록 하였다.

KOI 담당조교로 참가한 김진영 조교는 실수로 모든 학생의 프로그램을 날려 버렸다. 1등부터 N등까지 동석차 없이 등수를 매겨야 하는 김 조교는, 어쩔 수 없이 각 사람이 제출한 예상 등수를 바탕으로 임의로 등수를 매기기로 했다.

자신의 등수를 A등으로 예상하였는데 실제 등수가 B등이 될 경우, 이 사람의 불만도는 A와 B의 차이 ( |A-B| )로 수치화할 수 있다. 당신은 N명의 사람들의 불만도의 총 합을 최소로 하면서, 학생들의 등수를 매기려고 한다.

각 사람의 예상 등수가 주어졌을 때, 김 조교를 도와 이러한 불만도의 합을 최소로 하는 프로그램을 작성하시오.

 

입력


첫째 줄에 자연수 N이 주어진다. (1 ≤ N ≤ 500,000) 둘째 줄부터 N개의 줄에 걸쳐 각 사람의 예상 등수가 순서대로 주어진다. 예상 등수는 500,000 이하의 자연수이다.

 

출력


첫째 줄에 불만도의 합을 최소로 할 때, 그 불만도를 출력한다.

 

예제 입력과 출력

 

 

알고리즘 분류


그리디 알고리즘

정렬

 

정답

 

import sys

n=int(sys.stdin.readline().strip())
a=[0]*n
r=0

for i in range(n):
    a[i]=int(sys.stdin.readline().strip())

a.sort()

for i in range(n):
    r=r+ abs(a[i]-(i+1))

print(r)

 


백준 알고리즘 2012번 : www.acmicpc.net/problem/2012

 

2012번: 등수 매기기

첫째 줄에 자연수 N이 주어진다. (1 ≤ N ≤ 500,000) 둘째 줄부터 N개의 줄에 걸쳐 각 사람의 예상 등수가 순서대로 주어진다. 예상 등수는 500,000 이하의 자연수이다.

www.acmicpc.net

 

문제


상근이는 오락실에서 바구니를 옮기는 오래된 게임을 한다. 스크린은 N칸으로 나누어져 있다. 스크린의 아래쪽에는 M칸을 차지하는 바구니가 있다. (M

스크린의 위에서 사과 여러 개가 떨어진다. 각 사과는 N칸중 한 칸의 상단에서 떨어지기 시작하며, 스크린의 바닥에 닿을때까지 직선으로 떨어진다. 한 사과가 바닥에 닿는 즉시, 다른 사과가 떨어지기 시작한다.

바구니가 사과가 떨어지는 칸을 차지하고 있다면, 바구니는 그 사과가 바닥에 닿을 때, 사과를 담을 수 있다. 상근이는 사과를 모두 담으려고 한다. 이때, 바구니의 이동 거리의 최솟값을 구하는 프로그램을 작성하시오.

 

입력


첫째 줄에 N과 M이 주어진다. (1 ≤ M < N ≤ 10) 둘째 줄에 떨어지는 사과의 개수 J가 주어진다. (1 ≤ J ≤ 20) 다음 J개 줄에는 사과가 떨어지는 위치가 순서대로 주어진다.

 

출력


모든 사과를 담기 위해서 바구니가 이동해야 하는 거리의 최솟값을 출력한다.

 

예제 입력과 출력

 

 

알고리즘 분류


그리디 알고리즘

반복문

 

정답

 

import sys

n,m=map(int,sys.stdin.readline().split())
j=int(sys.stdin.readline().strip())
a=[]

for i in range(j):
    a.append(int(sys.stdin.readline().strip()))

s=1
e=m
c=0

for i in range(j):
    if s <= a[i] and e >= a[i]:
        continue
    if s > a[i]:
        c += s - a[i]
        e -= s - a[i]
        s = a[i]
    else:
        c += a[i] - e
        s += a[i] - e
        e = a[i]

print(c)

가장 짧게 이동하도록 바구니를 옮깁니다.

 


백준 알고리즘 2828번 : www.acmicpc.net/problem/2828

 

2828번: 사과 담기 게임

문제 상근이는 오락실에서 바구니를 옮기는 오래된 게임을 한다. 스크린은 N칸으로 나누어져 있다. 스크린의 아래쪽에는 M칸을 차지하는 바구니가 있다. (M 입력 첫째 줄에 N과 M이 주어진다. (1 ��

www.acmicpc.net

 

문제


한국도로공사는 고속도로의 유비쿼터스화를 위해 고속도로 위에 N개의 센서를 설치하였다. 문제는 이 센서들이 수집한 자료들을 모으고 분석할 몇 개의 집중국을 세우는 일인데, 예산상의 문제로, 고속도로 위에 최대 K개의 집중국을 세울 수 있다고 한다.

각 집중국은 센서의 수신 가능 영역을 조절할 수 있다. 집중국의 수신 가능 영역은 고속도로 상에서 연결된 구간으로 나타나게 된다. N개의 센서가 적어도 하나의 집중국과는 통신이 가능해야 하며, 집중국의 유지비 문제로 인해 각 집중국의 수신 가능 영역의 길이의 합을 최소화해야 한다.

편의를 위해 고속도로는 평면상의 직선이라고 가정하고, 센서들은 이 직선 위의 한 기점인 원점으로부터의 정수 거리의 위치에 놓여 있다고 하자. 따라서, 각 센서의 좌표는 정수 하나로 표현된다. 이 상황에서 각 집중국의 수신 가능영역의 거리의 합의 최솟값을 구하는 프로그램을 작성하시오. 단, 집중국의 수신 가능영역의 길이는 0 이상이며 모든 센서의 좌표가 다를 필요는 없다.

 

입력


첫째 줄에 센서의 개수 N(1<=N<=10,000), 둘째 줄에 집중국의 개수 K(1<=K<=1000)가 주어진다. 셋째 줄에는 N개의 센서의 좌표가 한 개의 정수로 N개 주어진다. 각 좌표 사이에는 빈 칸이 하나 이상 있으며, 좌표의 절댓값은 1,000,000 이하이다.

 

출력

 

첫째 줄에 문제에서 설명한 최대 K개의 집중국의 수신 가능 영역의 길이의 합의 최솟값을 출력한다.

예제 입력과 출력

 

 

알고리즘 분류


그리디 알고리즘

 

정답

 

import sys

n=sys.stdin.readline().strip()
k=int(sys.stdin.readline().strip())
a=list(map(int,sys.stdin.readline().split()))

b=sorted(a)
c=[]

for i in range(1,len(a)):
    c.append(b[i]-b[i-1])

c.sort()

for j in range(k-1):
    if len(c) == 0:
        c.append(0)
        break
    else:
        c.pop()
    
print(sum(c))

*리스트를 정렬하고 i 요소에서 i-1요소의 값을 빼줘 새로운 리스트에 저장합니다.

새로운 리스트에서 가장 큰 값부터 기지국 수 - 1 만큼 삭제하고 합을 계산합니다.

 

1 3 6 6 7 9

 2 3 0 1 2

 

2, 3, 0, 1, 2를 0, 1, 2, 2, 3으로 정렬하고 기지국 수(2)-1 만큼 삭제합니다.

0, 1, 2, 2의 합은 5로 집중국의 수신 가능 영역의 길이의 합의 최솟값입니다.

 


백준 알고리즘 2212번 : www.acmicpc.net/problem/2212

 

2212번: 센서

첫째 줄에 센서의 개수 N(1<=N<=10,000), 둘째 줄에 집중국의 개수 K(1<=K<=1000)가 주어진다. 셋째 줄에는 N개의 센서의 좌표가 한 개의 정수로 N개 주어진다. 각 좌표 사이에는 빈 칸이 하나 이상 있으며

www.acmicpc.net

 

문제


강호는 N개의 도시로 이루어진 나라에 살고 있다. 각 도시는 M개의 도로로 연결되어 있으며, 각 도로를 지날 때 필요한 시간이 존재한다. 도로는 잘 연결되어 있기 때문에, 도시 A에서 B로 이동할 수 없는 경우는 존재하지 않는다.

도시 A에서 도시 B로 바로 갈 수 있는 도로가 있거나, 다른 도시를 거쳐서 갈 수 있을 때, 도시 A에서 B를 갈 수 있다고 한다.

강호는 모든 쌍의 도시에 대해서 최소 이동 시간을 구해놓았다. 민호는 이 표를 보고 원래 도로가 몇 개 있는지를 구해보려고 한다.

예를 들어, 예제의 경우에 모든 도시 사이에 강호가 구한 값을 가지는 도로가 존재한다고 해도 된다. 하지만, 이 도로의 개수는 최솟값이 아니다. 예를 들어, 도시 1-2, 2-3, 1-4, 3-4, 4-5, 3-5를 연결하는 도로만 있다고 가정해도, 강호가 구한 모든 쌍의 최솟값을 구할 수 있다. 이 경우 도로의 개수는 6개이고, 모든 도로의 시간의 합은 55이다.

모든 쌍의 도시 사이의 최소 이동 시간이 주어졌을 때, 이 나라에 존재할 수 있는 도로의 개수의 최솟값과 그 때, 모든 도로의 시간의 합을 구하는 프로그램을 작성하시오.

 

입력


첫째 줄에 도시의 개수 N(1 ≤ N ≤ 20)이 주어진다. 둘째 줄부터 N개의 줄에 각각의 도시 사이에 이동하는데 필요한 시간 (≤ 10,000)이 주어진다. A에서 B로 가는 시간과 B에서 A로 가는 시간은 같다. 또, A와 B가 같은 경우에는 필요한 시간은 0이다.

 

출력

 

첫째 줄에 도로 개수가 최소일 때, 모든 도로의 시간의 합을 출력한다. 불가능한 경우에는 -1을 출력한다.

예제 입력과 출력

 

 

 

 

알고리즘 분류


그리디 알고리즘

플로이드 와샬 알고리즘

그래프 이론

 

정답

 

import sys

n = int(sys.stdin.readline().strip())
a = []
b = [[1]*n for i in range(n)]
c=0

for i in range(n):
    a.append(list(map(int, input().split())))

for i in range(n):
    for j in range(n):
        for k in range(n):
            if i == j or j == k or i == k:
                continue
            if a[j][k] == a[j][i] + a[i][k]:
                b[j][k] = 0
            elif a[j][k] > a[j][i] + a[i][k]:
                c = -1

if c != -1:
    for i in range(n):
        for j in range(i, n):
            if b[i][j] == 1:
                c += a[i][j]
print(c)

* i : 거쳐가는점

  j : 시작점 

  k : 끝점

 

j에서 k로 가는 최단경로와 j에서 i를 거쳐 k로 가는 최단경로의 합이 같으면 j에서 k로 가는 경로는 0으로 만들어줍니다.

j에서 k로 가는 최단경로의 값이 더 크면 c를 -1로 해서 출력합니다.


백준 알고리즘 1507번 : https://www.acmicpc.net/problem/1507

 

1507번: 궁금한 민호

강호는 N개의 도시로 이루어진 나라에 살고 있다. 각 도시는 M개의 도로로 연결되어 있으며, 각 도로를 지날 때 필요한 시간이 존재한다. 도로는 잘 연결되어 있기 때문에, 도시 A에서 B로 이동할

www.acmicpc.net

 

+ Recent posts