티스토리 뷰

코드포스 후기 #6


Codeforces Round #374 (Div. 2)
2016/09/30(금) 23:05



정신놓고 멍때리고 있다가 시간 다돼서 엉금엉금 컴퓨터 키고 11시에 사이트 들어갔는데 레지(참가자 등록)가 안되서 당황잼..!

시작 5분전부터는 레지가 안되는 줄 모르고 있다가 시작 후 10분 뒤부터 받는 엑스트라 레지 겨우 해서 참가했다ㅜㅜ

다행히 레지 안해도 문제 열람은 가능해서 A번 풀어놓고 레지 되자마자 제출하고 진행... 휴



A. One-dimensional Japanese Crossword

A번인데 막 그림까지 나와서 당황을 했지만 알고보니 내가 잘 아는 네모네모 로직(노노그램) 게임에 관련된 문제였다!

퍼즐의 한 줄이 B(Black)/W(White) 두 문자열의 조합으로 주어지고 이런 형태의 색칠을 이루는 네모네모 로직의 숫자표현을 찾는 문제.

처음부터 끝까지 스캔하면서 이전 문자와 지금 문자를 비교하면서 각각의 연속된 B들의 블록 길이를 알아낼 수 있다.



B. Passwords

주어진 password 후보들을 짧은 것부터 순서대로 입력할 때, real password가 입력되는 시간을 best case/worst case 두가지 각각 구하는 문제. 1개의 password 입력에는 1초가 소요되고 k번의 잘못된 입력마다 5초간 block이 된다.

문제 조건에서 입력 pw 들의 길이가 100자 이내이므로, 각각 pw의 길이를 구해서 길이별로 카운트한다.

일단 best/worst 모두 공통적으로 real pw 길이보다 짧은 pw들은 real pw보다 먼저 입력이 되므로, 이 짧은 pw들의 총 개수를 total로 누적한다.

best case는 real pw 길이와 같은 것들 중에서 real pw가 가장 먼저 입력되는 경우이다.

time = total + (total/k)*5 + 1

worst case는 real pw 길이와 같은 것들 중에서 real pw가 가장 나중에(더 긴 pw가 입력되기 직전) 입력되는 경우이다.

total += (real pw 길이와 같은 것들 개수, real pw 제외)

time = total + (total/k)*5 + 1



C. Journey

가중치가 있는 DAG(directed acyclic graph)에서 node 1→n까지 가장 많은 node를 거쳐서 가는 경로를 구하는 문제.

node, edge 갯수가 5000개 이하라서 그냥 dfs로 전체탐색했다가 TLE... (ㅠㅠ) 괜히 '자바문제일거야'하고 연장탓 하다가 C++로 고쳐서 냈는데도 TLE라서 내가 못난놈이구나 좌절하고... 자바로 풀어서 통과한 사람들도 있길래 일시적 멘붕ㅋㅋ 조금씩 고쳐서 다시 내봤지만 마지막까지 pass 못하고, 화나서(?) D번으로 넘어갔다.

끝나고 다른 사람들 풀이봤는데 dp를 썼더라. edge 갯수는 비교적 적지만 path를 따지자면 꽤 경우의 수가 많아지는 듯해서 dp로 상태를 저장해야 하는 듯 하다. 그래서 뒷북으로 dp 써서 다시 풀어봄!

dp[i][j] = (1→i 까지 오는데 길이 j인 path를 이루는 경우 걸리는 최단시간)

dpprev[i][j] = (위의 dp[i][j]의 시간이 걸리는 경우 i의 직전 node)

시간 제한인 T를 초과하지 않는 것에만 조건을 유의하면 구현은 까다롭지 않다.



D. Maxim and Array

주어진 수열 $\{a_i\}$에서 임의의 한 element에 $+x$ 또는 $-x$ 연산을 하는 것을 k번 수행했을 때 수열의 곱 $\displaystyle\prod_{i=1}^{n} a_i$이 최소가 되게 하는 문제. 가능한 결과 수열을 아무거나 출력하면 된다.

C번의 멘붕을 간직한 채로 D번을 풀었는데 뭔가 풀 수 있을 것 같아서 희망을...!! 가졌으나 막판에 5분정도 시간이 모자라서 제출을 못했다. 근데 나중에 제출해보니 50번째 TC에서 틀려서 어차피 틀렸을 듯...

50번째 TC는 big data기도 하고 사실 왜틀렸는지 데이터로 분석은 힘들어서 소스를 다시 엄청 뜯어봤는데, 결국 원인을 찾아서 제출했더니 pass 했다. 39 line의 등호가 빠져있었던 것(ㅠㅠ)


아무튼 풀이를 정리해보자.

문제에는 k번 이하의 연산을 해서 최소가 되게 하라고 했는데, 조금만 생각해보면 연산을 하면 0이 남아있을 때를 제외하고는 무조건 이전 상태보다 곱을 더 작은 숫자로 만들 수 있어서 greedy하게 진행해도 된다. 그리고 가능한한 곱을 양수→0→음수 방향으로 진행하는게 포인트!

먼저 (0인 것들을 제외하고)현재 수열의 곱이 +인지 -인지 판단하는 변수(isPositive)를 놓고 처음 입력받을 때 음수가 들어올 때마다 flip한다.

그리고 나서는 무조건 수열에서 가장 절대값이 작은 숫자 $a_i$ 를 찾아서(절대값으로 비교를 하는 priority queue를 사용) 그것에다가 아래와 같이 연산을 취한다. (이것을 k번 반복)

1) 현재 0들을 제외한 곱이 양수일 때,

 1-1) $a_i=0$ : $a_i$를 $a_i-x$로 바꾼다. 곱이 -로 바뀌어서 더 작아진다.

 1-2) $a_i>0$ : $a_i$를 $a_i-x$로 바꾼다. 바꾼 숫자가 음수이면 곱이 음수가 되어서 아주 좋은(?) 것이고, 음수가 안되더라도 곱이 줄어들게 된다.

 1-3) $a_i<0$ : $a_i$를 $a_i+x$로 바꾼다. 바꾼 숫자가 양수이면 (부호가 바뀌었으니)곱이 음수가 되어서 아주 좋은(?) 것이고, 양수가 안되더라도 절대값이 줄어든 것이기 때문에 이 경우도 결과적으로 곱이 줄어들게 된다.

2) 현재 0들을 제외한 곱이 음수일 때,

 이 경우는 1)보다 더욱 간단하다. 이미 곱이 음수인 상태이므로 절대값만 뿔려주면 된다. 양수에는 $+x$, 음수에는 $-x$, 0인 경우는 부호가 바뀌면 안되니깐 $+x$

+) 절대값이 가장 작은 숫자에다가 연산을 취하는 이유는 간단하게(?) 정리해보자면...

어쨌거나 위에서 말한대로 곱이 양수→0→음수의 방향으로 이동하게 해야하는데 최소값으로 만들려면 '곱이 감소하는 변화량의 폭을 최대로' 해야한다.

임의의 $a_k$에 연산을 취해서 $a_k \pm x$라고 가정하면, 

$S = \displaystyle\prod_{i=1}^{n} a_i = a_k \times S/a_k \\ \to (a_k \pm x) \times S/a_k = a_k \times S/a_k \pm x \times S/a_k = S \pm x \times S/a_k$

식에 따르면, +건 -건 연산을 취했을 때 곱의 변화량은 $x \times S/a_k$ 이고, 여기서 $x$와 $S$는 일정한 값이므로 $a_k$가 최소일 때 최대가 된다!



E. Road to Home

미제출





Final Standings

Rank

Points

Extras

A

500

B

1000

C

1500

D

2000

E

2750

951

1392

-

480

00:10

912

00:22

-3

지난 라운드랑 비슷한 결과다.(ㅠㅠ) 그래도 이미 pretest에서 pass 못해서 나중에 실망하는 일은 없었지만... C는 dp로 풀 생각도 안하고 있었으니 말아먹었다치고 D는 아슬아슬하게 풀 수 있었는데 아쉽다!



Rating Changes

Rank

Points

Rating

951

1392

1692 → 1681 (-11)


비슷하게 하락... 4문제 풀자는 다짐도 잠시 2문제의 늪에 빠지고 있구나ㄷㄷ

그나마 다행인건 친구한테는 이김-_-ㅋ



이번에는 나름 끝난 다음에도 문제풀이 조금 더 했다는데(E까지는 안했지만...) 의의를 두고있다. 하하

그리고 밀린거 쓴게 아니라 따끈따끈한(?) 후기라서 문제마다 내용을 더 상세하게 기록하기도 했고.

대회를 여러번 참가할 수록 자바로 하는게 약간 불만이 늘어가는데 C++로 언제 갈아탈 수 있을까ㅠㅠ

아! 그리고 또하나의 교훈! "레지는 미리 하자"



※ 링크 : 대회공지 / 출제자해설


'알고리즘 > Codeforces' 카테고리의 다른 글

Codeforces Magic! New Year Gift  (0) 2017.01.10
Codeforces Round #375 (Div. 2)  (0) 2016.10.06
Codeforces Round #373 (Div. 2)  (0) 2016.09.30
Codeforces Round #372 (Div. 2)  (0) 2016.09.29
Codeforces Round #371 (Div. 2)  (0) 2016.09.28
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2025/09   »
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
글 보관함