NYPC 문제풀이
개요
NYPC 는 넥슨에서 개최하는 청소년 프로그래밍 대회입니다.
매년 여름방학 시즌에 진행되어 비교적 학업에 지장을 덜 받고 출전해 볼 수
있습니다.
학원생 중 이 대회를 준비하는 친구들이 많아 문제풀이를 지속적으로 업데이트할 계획입니다.
자세한 대회 세부 요강 및 기출문제는 NYPC 홈페이지를 참조하기 바랍니다.
NYPC 2024
[본선1519, 라운드기록 복원하기]
https://nypc.github.io/2024/final_3
현재 48점 🤔
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 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 | n,k = map ( int , input ().split( ' ' )) s = input () # 첫 i 개의 라운드가 진행되었을 때 팀 점수차로 가능한 값들의 집합. D = [ set () for _ in range (n + 1 )] # 마지막에서 i 번째 라운드가 진행되었을 때 팀 점수차로 가능한 값들의 집합. E = [ set () for _ in range (n + 1 )] # 0라운드 초기값 D[ 0 ].add( 0 ) E[ 0 ].add(k) E[ 0 ].add( - k) # D[i] 계산, 1라운드부터 진행, ?B?R->RBRR for i in range ( 1 , n + 1 ): if s[i - 1 ] = = 'R' : V = { 1 } elif s[i - 1 ] = = 'B' : V = { - 1 } else : V = { 1 , - 1 } # ?일때 V는 {1, -1} for j in D[i - 1 ]: for v in V: diff = j + v # 유효점수 차이 범위 확인 if - k + 1 < = diff < = k - 1 : D[i].add(diff) #print(D) # # E[i] 계산, 마지막 라운드부터 역으로 진행 for i in range ( 1 , n + 1 ): if s[n - i] = = 'R' : V = { 1 } elif s[n - i] = = 'B' : V = { - 1 } else : V = { 1 , - 1 } for j in E[i - 1 ]: for v in V: diff = j - v if - k + 1 < = diff < = k - 1 : E[i].add(diff) #print(E) result = list (s) # 현재 점수 차이 diff = 0 # 유실된 라운드 복구 for i in range (n): if s[i] = = '?' : red = diff + 1 in D[i + 1 ] and diff + 1 in E[n - i - 1 ] blue = diff - 1 in D[i + 1 ] and diff - 1 in E[n - i - 1 ] #print(s[i], red, blue, diff) if red and not blue: result[i] = 'R' diff + = 1 elif blue and not red: result[i] = 'B' diff - = 1 # 복구 불가능 else : if n - 1 = = i and k! = diff: if diff< 0 : result[i] = 'B' elif diff> 0 : result[i] = 'R' else : #print(s[i], diff) if s[i] = = 'R' : diff + = 1 else : diff - = 1 print (''.join(result)) |
NYPC 2023
[본선1214, 영국우편번호]
https://nypc.github.io/2023/final_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 | def isAlpha(c): if ord (c)> = ord ( 'A' ) and ord (c)< = ord ( 'Z' ): return True return False def isNumber(c): if ord (c) > = ord ( '0' ) and ord (c)< = ord ( '9' ): return True return False def checkPost(s, rule): p = '' for c in s: if isAlpha(c): p + = 'A' elif isNumber(c): p + = '9' if p in rule: return True return False m = int ( input ()) front_rule = ( 'AA9A' , 'A9A' , 'A9' , 'A99' , 'AA9' , 'AA99' ) end_rule = ( '9AA' ,) for i in range (m): a, b = input ().split( ' ' ) f = checkPost(a, front_rule) e = checkPost(b, end_rule) if f and e: print ( 'YES' ) else : print ( 'NO' ) |
[예선문제, 인류의 적 모기 퇴치]
https://nypc.github.io/2023/round1_p1
N*N 배열마다 십자가, 대각선방향으로 -m 부터 +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 28 29 30 31 32 33 34 35 36 37 38 | n, m = map ( int , input ().split( ' ' )) lst = [ None for _ in range (n)] for i in range (n): temp = list ( map ( int , input ().split( ' ' ))) lst[i] = temp mcnt = set () for i in range (n): for j in range (n): # cross cnt = 0 vs = i - m if i - m> = 0 else 0 ve = i + m + 1 if i + m + 1 <n else n hs = j - m if j - m> = 0 else 0 he = j + m + 1 if j + m + 1 <n else n for r in range (vs, ve): cnt + = lst[r][j] for c in range (hs, he): if c! = j: cnt + = lst[i][c] mcnt.add(cnt) # diagonal cnt = 0 for k in range ( - m, m + 1 ): if (i + k> = 0 and i + k<n) and (j + k> = 0 and j + k<n): cnt + = lst[i + k][j + k] if (i + k> = 0 and i + k<n) and (j - k> = 0 and j - k<n): if k! = 0 : cnt + = lst[i + k][j - k] mcnt.add(cnt) print ( max (mcnt)) |
[예선문제, 메이플 새로운 직업고르기]
https://nypc.github.io/2023/round1_1
입력받은 직업을 배열에 저장한 후 키워본 직업을 입력받아 리스트에서 제거.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | n = int ( input ()) jobList = [] for _ in range (n): job = input () jobList.append(job) k = int ( input ()) for _ in range (k): job = input () if job in jobList: jobList.remove(job) print ( len (jobList)) for job in jobList: print (job) |
[예선문제, 게임 안에서 책을 읽을 수 있다구요?]
https://nypc.github.io/2023/round1_2
입력받은 한줄을 공백을 기준으로 나누고 각 단어들의 시작인덱스와 끝 인덱스를 정리.
단어들의 끝 인덱스가 문서의 폭보다 작은 경우 앞단어의 시작과 끝을 연결시켜
나가며 처리.
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 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 | def parsingLine(line): words_idx = [] if len (line.split( ' ' )) = = 1 : words_idx.append(( 0 , len (line) - 1 )) else : k = 0 for i in range ( len (line)): if line[i] = = ' ' : words_idx.append((k, i - 1 )) k = i + 1 words_idx.append((k, len (line) - 1 )) #print(words_idx) new_idx = [] s = 0 e = 0 k = 0 for i, v in enumerate (words_idx): if v[ 1 ] - v[ 0 ] + k + 1 < = m: e = v[ 1 ] k + = v[ 1 ] - v[ 0 ] + 1 else : new_idx.append( (s, e) ) s = v[ 0 ] e = v[ 1 ] k = e - s + 1 k + = 1 new_idx.append( (s, e) ) #print(new_idx) return new_idx def noTag(line): new_idx = parsingLine(line) new_line = '' for s, e in new_idx: word = line[s:e + 1 ].replace( ' ' , '-' ) k = m - len (word) if k = = 0 : new_line + = word else : while len (word)<m: word + = '-' new_line + = word new_line + = '\n' return new_line[: - 1 ] def centerTag(line): new_idx = parsingLine(line) new_line = '' for s, e in new_idx: word = line[s:e + 1 ].replace( ' ' , '-' ) k = m - len (word) if k = = 0 : new_line + = word elif k = = 1 : new_line + = word + '-' else : new_line + = '-' * (k / / 2 ) + word + '-' * (k / / 2 ) if k % 2 = = 1 : new_line + = '-' new_line + = '\n' return new_line[: - 1 ] def rightTag(line): new_idx = parsingLine(line) new_line = '' for s, e in new_idx: word = line[s:e + 1 ].replace( ' ' , '-' ) k = m - len (word) if k = = 0 : new_line + = word else : while len (word)<m: word = '-' + word new_line + = word new_line + = '\n' return new_line[: - 1 ] def getAlignText(line, tag = 0 ): #tag 0:none, 1:center, 2:right if line = = '<CENTER>' : return '', 1 elif line = = '<RIGHT>' : tag = 2 return '', 2 elif line = = '</CENTER>' or line = = '</RIGHT>' : return '', 0 else : if tag = = 0 : return noTag(line), tag elif tag = = 1 : return centerTag(line), tag else : return rightTag(line), tag n,m = map ( int , input ().split( ' ' )) lines = [] for _ in range (n): s = input () lines.append(s) tag = 0 for line in lines: newLine, tag = getAlignText(line, tag) if newLine: print (newLine) |
NYPC 2022
[본선문제, 조약돌 순서]
https://nypc.github.io/2022/final_1
반복의 횟수를 줄여야 하고 Python의 경우 List 자료형으로 인덱스 접근, deque 자료형으로 Rotation을 처리해서 시간제한을 돌파.
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 | import sys from collections import deque s = sys.stdin.readline().rstrip() k, n = map ( int , s.split( ' ' )) if n = = 0 : for i in range (k): sys.stdout.write(f '{i+1} ' ) else : x = deque([ str (i + 1 ) for i in range (k)]) z = n / / (k - 1 ) % k for i in range (z): x.rotate( - 1 ) z = n % (k - 1 ) x = list (x) for i in range (z): temp = x[i] x[i] = x[i + 1 ] x[i + 1 ] = temp for c in x: sys.stdout.write(c + ' ' ) print () |
NYPC 2018
[예선문제, 아이템구매]
https://nypc.github.io/2018/2018_online_3.html
부정방정식을 푸는 문제
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | # y에 대한 방정식 # 1. ax + by = c # 2. by = c-ax # 3. y = (c-ax)/b p, q, w = map ( int , input ().split( ' ' )) i = 1 while i * p < = w: if (w - (i * p)) % q = = 0 : print (i, (w - (i * p)) / / q) break i + = 1 |
[예선문제, 승리팀찾기]
https://nypc.github.io/2018/2018_online_4.html
아이템전은 가장 빠른 시간을 찾아 그 팀을 출력하고 스피드전은 정렬 후 등수점수를 팀별로 합산.
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 | def itemWinner(records): best = records[ 0 ][ 1 ] idx = 0 for i in range ( 8 ): if best > records[i][ 1 ]: best = records[i][ 1 ] idx = i return records[idx][ 0 ] def speedWinner(records): # sort for i in range ( 8 - 1 ): for j in range (i + 1 , 8 ): if records[i][ 1 ]>records[j][ 1 ]: temp = records[i] records[i] = records[j] records[j] = temp best = records[ 0 ][ 1 ] red_score = 0 blue_score = 0 score = ( 10 , 8 , 6 , 5 , 4 , 3 , 2 , 1 ) for i in range ( 8 ): if records[i][ 1 ] - best< 10 : if records[i][ 0 ] = = 'red' : red_score + = score[i] else : blue_score + = score[i] if red_score>blue_score: return 'red' elif blue_score>red_score: return 'blue' else : return records[ 0 ][ 0 ] #input n = int ( input ()) for _ in range (n): k = input () records = [] for _ in range ( 8 ): t, r = input ().split( ' ' ) minu, sec = map ( float , r.split( ':' )) records.append((t, minu * 60 + sec)) if k = = 'item' : print (itemWinner(records)) else : print (speedWinner(records)) |
[예선문제, 줄임말]
https://nypc.github.io/2018/2018_online_5.html
파이썬으로 풀면 쉬운문제. 공백을 기준으로 문장을 잘라내서 UTF-8로
저장.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | n = int ( input ()) try : f = open ( 'ouput.txt' , mode = 'w' , encoding = 'utf-8' ) except Exception as e: print (e) else : for i in range (n): lst = input ().split( ' ' ) for word in lst: f.write(word[ 0 ]) if i! = n - 1 : f.write( '\n' ) f.close() |
[예선문제, 우물왕 김배찌]
https://nypc.github.io/2018/2018_online_6.html
분산을 최소화하는 대표값은 평균.
1 2 3 4 5 6 7 8 9 | n = int ( input ()) xp = 0 yp = 0 for _ in range (n): x, y = map ( int , input ().split( ' ' )) xp + = x yp + = y print (xp / n, yp / n) |
[예선문제, 최고의 동접구간을 찾아라]
https://nypc.github.io/2018/2018_online_7.html
예제 입력은 다 해결했는데 BIKO 제출시 틀렸다는데 반례를 모르겠다. 일단은 여기까지..
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 59 60 | def hourToMin(hour): h, m = map ( int , hour.split( ':' )) return h * 60 + m def minToHour( min ): h = min / / 60 m = min % 60 return f '{h:02}:{m:02}' n = int ( input ()) records = [] for i in range (n): login, logout = input ().split( ' ' ) records.append( (hourToMin(login), True ) ) records.append( (hourToMin(logout), False ) ) # sort records.sort(key = lambda x: x[ 0 ]) from collections import defaultdict counts = defaultdict( set ) for num, flag in records: counts[num].add(flag) # 중복되는 항목을 확인 to_remove = {num for num, flags in counts.items() if len (flags) > 1 } # 중복되는 항목을 제거한 새로운 리스트 생성 records = [item for item in records if item[ 0 ] not in to_remove] #print(records) # find segmemt user = 0 max_user = 0 max_seg = 0 start_time = 0 k = len (records) for i in range (k): isIn = records[i][ 1 ] if isIn: user + = 1 else : user - = 1 if user>max_user: start_time = records[i][ 0 ] max_user = user max_seg = i #print(user) print (max_user) print (minToHour(start_time), end = ' ' ) for i in range (max_seg + 1 , k): if records[i][ 1 ] = = False : print (minToHour(records[i][ 0 ])) break |
지속적으로 업데이트 예정입니다.
댓글
댓글 쓰기