해설
선물을 많이 주는 방법으로 금액을 나누어야 한다 ...
할인은 한명만 가능하고 , 배송비는 별도로 할인이 안된다 .
즉 , 친구들 중 가격이 낮은 ( 물건 + 배송비 ) 순으로 배송을 보내는 것이 가장 이상적이다 .
가격이 낮은 순으로 정렬하고 , 한명씩 할인된 가격과 비교해서 많이 보낼 수 있는 값을
찾는다 .
입력
각각 친구들의 물건값 , 배송비를 입력받는다 .
N , B = map ( int , input (). split ())
gifts = []
for i in range ( N ):
item = list ( map ( int , input (). split ()))
gifts . append ( item )
물건 값과 배송비 순으로 오름차순으로 정렬한다 .
gifts . sort ( key = lambda x : ( x [ 0 ], x [ 1 ]))
정렬된 데이터에서 i 번째가 할인했을 때 총비용을 costs에 저장하고 , 다시 정렬한다 .
그러면 , 각각 친구들에게 배송비를 포함해서 정렬되고 ,
비용이 costs에 저장되어있으니 이제 부터 합해서 보낸 횟수를 증가 시킨다 .
내 돈을 넘으면 멈추고 , 아니라면 최대 횟수와 비교해서 값을 저장한다 .
max = 0
# print(gifts)
for i in range ( N ):
costs = []
for j in range ( N ):
cost = 0
if i == j :
cost = ( gifts [ j ][ 0 ] / 2 ) + gifts [ j ][ 1 ]
else :
cost = gifts [ j ][ 0 ] + gifts [ j ][ 1 ]
costs . append ( cost )
costs . sort ()
sum = 0
p_count = 0
for h in range ( N ):
sum += costs [ h ]
p_count += 1
if sum > B :
break
else :
if max < p_count :
max = p_count
이 일련의 과정을 모두 거치면 max에는 보낸 횟수의 최대값이 들어감으로
출력한다 .
답안
if __name__ == '__main__' :
N , B = map ( int , input (). split ())
gifts = []
for i in range ( N ):
item = list ( map ( int , input (). split ()))
gifts . append ( item )
gifts . sort ( key = lambda x : ( x [ 0 ], x [ 1 ]))
max = 0
# print(gifts)
for i in range ( N ):
costs = []
for j in range ( N ):
cost = 0
if i == j :
cost = ( gifts [ j ][ 0 ] / 2 ) + gifts [ j ][ 1 ]
else :
cost = gifts [ j ][ 0 ] + gifts [ j ][ 1 ]
costs . append ( cost )
costs . sort ()
sum = 0
p_count = 0
for h in range ( N ):
sum += costs [ h ]
p_count += 1
if sum > B :
break
else :
if max < p_count :
max = p_count
print ( max )
현재 있는 체스 피스의 개수가 기존에 있어야 할 피스 개수와 맞는지 출력한다.
해설
이전 문제들과 달리 입력받는 개수가 많다. c1, c2, c3… 이런식으로 변수를 작성해도 괜찮지만, 매번 입력마다 저 변수를 모두 작성하기는 어렵다.
이럴때 필요한 것이 리스트 이다.
리스트란, 데이터들을 순서대로 배치해서 관리하는 자료 구조이다.
예를 들면, 학생들이 많은 경우 학번을 붙여서 조회가 가능한데, 동일한 이름을 가지더라도 학번을 이용하면 누가 누구인지 분류가 가능하다.
student = [ 'sara' , 'sara' ]
sara 라는 학생이 2명있다고 하는 경우 각각 student[0], student[1]로 접근이 가능하다.
나중에 첫번째 sara의 이름을 sarah 로 바꿀때에도 student[0] = ‘sarah’ 이런식으로 작성하면 된다.
주의!
리스트는 배열이 아닙니다… (index의 유무가 있는데요. 설명을 위해서는 메모리와 노드를 설명해야하는데 참고자료 로 대신 설명 드립니다.)
우선 한 세트로 인식하는 chess 리스트를 아래와 같이 작성한다 .
chess = [ 1 , 1 , 2 , 2 , 2 , 8 ]
이렇게 작성하고 입력한 체스 리스트와 비교해서 출력하면 된다 .
** 입력 **
list 형태로 적용해야되기 때문에 메소드 list () 를 이용한다 .
이전 문제에서 본 것 같이 map 을 통해서 각각의 값을 int로 두고 공백에 따라 분리한다 .
chess_list = list ( map ( int , input (). split ()))
** 기본 세트와 비교 **
이제 리스트들이 있는데 , 해당 리스트들을 서로 비교해야한다 . 이때 for문을 이용하는데 ,
for i in range ( 0 , 6 ):
result += str ( chess [ i ] - chess_list [ i ]) + ' '
여기서 range ( 0 , 6 ) 을 range ( 6 ) 으로 둘 수 있다 .
0 ~ 5 까지를 i로 두고 각각 아래에 해당하는 코드를 실행하는 것을 의미한다 .
6 은 포함하지 않기 때문에 주의하자 .
기존 세트의 체스 개수 , 입력 받은 값을 빼서 str로 둔다 . 이를 실제 출력에 맞도록
공백을 추가하면 result 그대로 답변이 된다 .
** 출력 **
print ( result )
답안
if __name__ == '__main__' :
chess = [ 1 , 1 , 2 , 2 , 2 , 8 ]
chess_list = list ( map ( int , input (). split ()))
result = ''
for i in range ( 0 , 6 ):
result += str ( chess [ i ] - chess_list [ i ]) + ' '
print ( result )
해설
입력들을 한줄씩 받고 , 해당 값의 평균과 중앙값을 반환하면 된다 .
입력받는 것은 5 개로 평균은 간단히 총합을 5 로 나누면 된다 !
nums = []
for i in range ( 5 ):
n = int ( input ())
nums . append ( n )
여기서 총합을 입력 받고 나서 별도로 더하는 방법도 있지만 ,
입력받는 즉시 더해두면 시간을 더 줄일 수 있다 .
이를 sum에다 넣어두고 마지막 출력에 나누기를 하자 .
이제 중앙값이 문제인데 , 중앙값을 알려면 수들을 정렬해야한다 .
숫자들의 개수가 5 개이기 때문에 3 번째 놓인 수가 중앙값이다 !
** 출력 **
따라서 출력할때 평균 , 중앙값 순이기 때문에 ... 아래와 같이 된다 .
**** print ( int ( sums / 5 ))
print ( nums [ 2 ])
여기서 평균에 int ( sum / 5 ) 를 하는 이유는 평균 , 중앙값이 모두 자연수 이기
때문이다 .
답안
if __name__ == '__main__' :
nums = []
sums = 0
for i in range ( 5 ):
n = int ( input ())
nums . append ( n )
sums += n
nums = sorted ( nums )
print ( int ( sums / 5 ))
print ( nums [ 2 ])
해설
9 X9 판에서 몇행 몇열에 최대값이 있는 지 찾는 문제이다 .
어떻게 구현할지 생각해보면 ...
'하나씩 숫자를 탐색하면서 최대값을 찾은 후 해당 격자판에서 최대값과
같은수가 위치한 행,열을 출력한다.'
라고 생각할 수 있지만 , 최대값을 찾는데 전체 탐색 , 다시 최대값이 있는
위치를 찾기위해 전체 탐색으로
총 2 번 전체탐색을 하는 것은 비효율적이다 .
그렇기 때문에 한가지 생각을 해보면 ...
한줄씩 입력을 받기 때문에 한 행당 큰수를 얻을 수 있다 . 입력받은 즉시
큰 값에 대한 위치 ( index ) 를 저장시켜둔다 .
nums = []
point = []
for i in range ( 9 ):
l = list ( map ( int , input (). split ()))
ml = max ( l )
nums . append ( ml )
point . append ( l . index ( ml ))
이렇게 해두면 . nums 에는 한 행당 가장 큰수들이 저장되고 , point에는 각
행의 큰수가 몇번째 열에 있는지 저장된다 .
그렇다면 nums에서 큰수는 격자판에서 가장 큰수이고 , point에는 큰수들이 몇
번째 열에 있는지 저장되었기 때문에 큰수의 열을 알 수 있다 .
max = max ( nums )
print ( max )
ind = nums . index ( max )
print ( ind + 1 , point [ ind ] + 1 )
최대값을 출력하고 , 최대값의 행열을 각각 출력하면 된다 .
답안
if __name__ == '__main__' :
nums = []
point = []
for i in range ( 9 ):
l = list ( map ( int , input (). split ()))
ml = max ( l )
nums . append ( ml )
point . append ( l . index ( ml ))
max = max ( nums )
print ( max )
ind = nums . index ( max )
print ( ind + 1 , point [ ind ] + 1 )
해설
총 금액과 영수증의 금액이 일치하지 않으면 No 를 일치하면 Yes를 출력한다 .
첫 입력으로 total ( 총 금액 ) 을 입력 받는다 .
이후 영수증에 종류 수 N 에 따라서 입력을 받는다 .
for i in range ( item_count ):
cost , count = map ( int , input (). split ())
이때 입력을 따로 저장해두지 않고 입력 받는 즉시 total ( 총 금액 ) 에서 빼면
코드를 좀더 줄일 수 있다 .
결과적으로 총 금액과 일치하는 지 아닌지 체크하면 되기 때문에
N ( 물건 개수 ) 를 전부 입력 받은 뒤 total 이 0 인지 체크하면 된다 .
if total == 0 :
print ( 'Yes' )
else :
print ( 'No' )
답안
if __name__ == '__main__' :
total = int ( input ())
item_count = int ( input ())
for i in range ( item_count ):
cost , count = map ( int , input (). split ())
total -= cost * count
if total == 0 :
print ( 'Yes' )
else :
print ( 'No' )
해설
시계에서 60 분은 1 시간이고 24 시 인 경우가 0 시 인점만 주의하면 됩니다 .
여기서 주의 할 점은 문제를 봤을 때 단순히 덧셈 뺄셈이 아닌 나누기 , 나머지
로 봐야한다는 점이다 .
이번에 메소드 def 문과 같이 코드를 작성하면
def calculate ( h , m ):
h += int ( m / 60 )
h = int ( h % 24 )
m = int ( m % 60 )
print ( str ( h ) + ' ' + str ( m ))
처럼 분이 60 을 넘은 경우 ( ex : 120 , 150 등 ) 에 맞게 h ( hour ) 에 더한다 .
h 가 24 를 넘는 경우는 0 시 부터 시작하기 때문에 24 로 나눈 나머지가 시간으로
된다 . ( ex : 26 시는 24 로 나눈 나머지 2 시가 된다 .)
시간으로 나간 것 이외의 나머지 분을 기존 m ( 나눈 나머지가 현재 minute가 된다 .) 로 둔다 .
이렇게 하면 , 요리가 끝난 시간을 각각 출력 할 수 있다 .
print ( str ( h ) + ' ' + str ( m ))
답안
def calculate ( h , m ):
h += int ( m / 60 )
h = int ( h % 24 )
m = int ( m % 60 )
print ( str ( h ) + ' ' + str ( m ))
if __name__ == '__main__' :
h , m = map ( int , input (). split ())
time = int ( input ())
m += time
calculate ( h , m )
해설
새싹을 출력하면 되는데 …
우리가 print로 출력할 때 ‘’ , 또는 “” 를 이용한다 .
출력을 해야하는 곳에 ‘ 또는 “ 이 있다면 해당 문자를 출력할 것으로 보지 않고
코드로 인식하기 때문에 바로 출력하기 위해서는 \ 를 붙여 주어야 한다 .
답안
if __name__ == '__main__' :
print ( ' ,r \' "7' )
print ( 'r`-_ , \' ,/' )
print ( ' \. \" . L_r \' ' )
print ( ' `~\/' )
print ( ' |' )
print ( ' |' )
이번 문제는 a^2 - b^2 공식인 (a+b)(a-b)를 이용해야한다.
해설
성원이가 살이 쪘는데 , 부끄러운 나머지 얼마나 쪘는지 안 알려주고
a ^ 2 - b ^ 2 이런식으로 알려주었다 ...
기존 몸무게도 모르기 때문에 위 공식에서 연립 방정식을 푸는 방식으로 진행해야한다 .
위 공식은 기존에 ( a + b )( a - b ) 이다 . a , b 양수라는 조건이 있기 때문에 ( 몸무게니깐 )
a + b가 무조건 큰 수로 두고 , 쪘다고 했으니 a ^ 2 을 찐 몸무게로
인식하고 출력하면된다 .
우선 연립 방정식으로 만들어야 하는데 , 결과적으로 ( a + b )( a - b ) 는
입력 받는 G 값의 약수이기 때문에 추론이 가능하다 .
여기까지 풀이 과정을 정리하면
1. G의 약수를 찾는다 .
2. 약수에 맞게 a , b를 찾는다 .
3. a , b 가 양수인 경우 오름차순으로 출력하고 ,
맞는 값이 없으면 - 1 을 출력한다 .
1. G의 약수 찾기
약수를 찾는 것은 많은 방법이 있지만 , 주로 가장 효율적인 방식은 제곱근 까지 나누어서
0 인 것을 약수로 두는 것이다 . ( 약수에는 제곱근을 기준으로 대칭 으로 짝이 있기 때문에 )
하지만 , 문제에서 해당 범위가 생각보다 적기 때문에 단순히 1 ~ G까지만 체크했다 .
그것이 아래 코드이다 .
for i in range ( 1 , G + 1 ):
if int ( G % i ) == 0 :
여기서 int ( G % i ) == 0 인 것은 약수로 판정된다 .
위에서 설명한 대로 a + b가 2 개의 약수중 큰 약수이기 때문에 ...
약수에 맞는 a , b를 찾을 때 염두해야한다 .
2. 약수에 맞게 a , b를 찾기
여기서 나는 별도의 메소드로 분리 시켜두었는데 , a , b가 헷갈리기 때문에 조금 바꾸면 ..
def possible ( c , d ):
for p in range ( 1 , d ):
if c + p == d - p :
return ( c + p )
해당 메소드를 호출하는 시점은 약수 ( i , int ( G / i )) 가 구해지고 각각 넣게 된다 .
result = possible ( i , int ( G / i ))
위 메소드에서 c , d는 각각의 약수로 .. 기존 연립 방정식은 다음과 같다 .
a + b = d
a - b = c
여기서 의문스러운 것은 c와 d의 위치가 바뀔 수 있지 않느냐 인데 , 해당
메소드가 1 ~ G까지 약수 조합 모두 ( 1 , G ) ~ ... ~ ( G , 1 ) 을 체크하기 때문에
순서 고려 없이 진행해도 된다 . d가 무조건 큰수여야 한다는 조건이 맞지 않으면 ,
답 역시 달라지기 때문 .( 수식 성립 안됨 -> 음수여야 풀리기 때문 )
우리가 구할 것은 가능한 a와 b 이다 . a를 남기고 넘기면
a = d - b
a = c + b 이다 .
이것이 if c + p == d - p : 에 해당하는 조건문이고 , b로 가능한 .. 범위
( 1 ~ d ) 까지 b를 대입시켜서 구하면 ... p로 각각 비교한다 .
조건에 맞는 a와 b ( p ) 가 있다면 해당 값을 리턴한다 .
3. 출력하기
이렇게 리턴 된 값을 divisor에 추가 시키고 , 값이 있는 경우 sorted 후 출력 ,
없다면 - 1 출력을 한다 .
답안
def possible ( a , b ):
for p in range ( 1 , b ):
if a + p == b - p :
return ( a + p )
if __name__ == '__main__' :
G = int ( input ())
divisor = []
for i in range ( 1 , G + 1 ):
if int ( G % i ) == 0 :
result = possible ( i , int ( G / i ))
if result != None :
divisor . append ( result )
for j in sorted ( divisor ):
print ( j )
if len ( divisor ) == 0 :
print ( - 1 )
해설
N개의 문자가 있고 , 다음으로 주어지는 M개의 문자들에 포함되어있는지
찾는 문제로 ...
N 의 문자들이 M에 몇개가 있는지 체크하면 된다 .
파이썬에서는 count를 이용해서 간단히 체크할 수 있기 때문에 각각
for i in range ( N ):
result += m_group . count ( n_group [ i ])
이런 식으로 m 들의 입력에서 count ( n 문자 ) 를 이용해 포함되는 개수를
더하면 된다 .
답안
if __name__ == '__main__' :
N , M = map ( int , input (). split ())
n_group = []
m_group = []
result = 0
for i in range ( N ):
n_group . append ( input ())
for j in range ( M ):
m_group . append ( input ())
for i in range ( N ):
result += m_group . count ( n_group [ i ])
print ( result )
해설
악마의 숫자 666 !
세상의 종말을 나타낸다고 하지만 사실상 악마의 숫자를 순화한게 아닐까 .. ?
크흠 아무튼 , 세상의 종말이라는 시리즈 영화감독으로
각 제목에 666 이 반드시 포함하도록 넘버링을 한다고 한다 .
각 시리즈를 거듭할때 마다 666 을 포함하고 , 커져야 하기 때문에
이를 구현할 방법을 생각해봐야한다 .
666 을 반드시 포함한 N번째 영화에 붙는 숫자를 구하는 것이고 ... N이 10 , 000
보다 작거나 같다 . 거기에 2 초라는 시간 제한을 생각해보면
666 부터 쭉 증가 시키면서 666 이 포함된 경우에 카운트하고 카운트가 N
이 되는 순간에 수를 더이상 증가시키지 않으면 된다 .
N = int ( input ())
count = 0
num = 666
while ( 1 ):
st_n = str ( num )
if st_n . find ( '666' ) != - 1 :
count += 1
if count == N :
break
num += 1
이를 통해서 위와 같이 작성하면 된다 .
num + 1 을 하기전에 count가 N번째인지 체크하여서 ,
N이라면 반복문을 break로 빠져나온다 .
N번째 번호가 아니라면 if문을 통해 가지 않고 그대로 코드를 실행하기 때문에
num + 1 을 하게 된다 .
마지막으로 N번째에 대한 번호를 출력한다 !
print ( num )
답안
if __name__ == '__main__' :
N = int ( input ())
count = 0
num = 666
while ( 1 ):
st_n = str ( num )
if st_n . find ( '666' ) != - 1 :
count += 1
if count == N :
break
num += 1
print ( num )
© 2021. All rights reserved. LICENSE | NOTICE | CHANGELOG
Powered by Hydejack v9.1.6