강의로 돌아가기
전현서

쿠키 구입 해설.

2명의 자식에게는 항상 공평해야한다.
그것이 형이건 아우건, 공평하지 않으면 싸움이 일어나기 마련이다.
어린 시절에 부모님이 자식들에게 차별대우를 하면, 차별 당한 한 명은 열등감이 생긴다.
열등감을 이용하여, 남들보다 뛰어난 업적을 이룰수도 있지만, 그 차이가 심하다면, 좌절감을 느껴 주눅늘게 된다.
이런 현상은 우리 주변에서 많이 볼 수 있으며, 사람이 성장함에 있어서, 매우 좋지 않은 감정을 가지게 한다.
이 문제는 이런 현상을 미연에 방지하고자, 사이좋게 두 형제가 쿠키를 가질 수 있게 도와준다.
아주 좋은 취지라고 필자는 생각한다.

하지만, 그냥 반띵하면 될 것을 굳이 가져가는 순서를 정해서, 오지게 힘들게 한다.
정말 나도 힘들다.

농담이고, 첫 시작점이, i 라고하고, 첫 끝점이 m이라고 하면,
첫째는, cookie[i] + cookie[i+1] + ... + cookie[m] 만큼의 쿠키를 가져가게 된다.
둘째는 m+1부터 r까지의 쿠키를 가져 갈 수 있고, i <= m <= r 의 관계를 갖는다.
그 의미는 둘째는 절대로 첫째가 가져가는 쿠키 범위보다 앞에 있는 것을 가져갈 수 없다는 의미이다.
둘째는 첫째가 가져간 범위 이후의 바로 이어진 쿠키를 가져가야만 한다. 즉, 첫째의 끝점에 의해서, 둘째의 시작점이 정해진다.
둘째는 기분이 그리 좋지 않을 것이다. ㅠㅠㅠ
둘째는 cookie[m+1] + cookie[m+1] + ... + cookie[r] 만큼의 쿠키를 가져가게 된다.
그리고 두 값이 같으면서 최대가 되는 지점을 구하는 것이 이 문제의 목표가 된다.

즉, sum( cookie[i~m]) == sum(cookie[m+1~r]) 이 되고, 이 값이 문제에서 나올 수 있는 경우 중 가장 큰 값을 구해야한다.
쿠키 최대값의 한계는 쿠키 전체의 수량 합에서 2로 나눈 값이 되는 것을 쉽게 알 수 있을 것이다.

생각보다, 이 문제를 푸는 방법은 매우 쉽다.
중심 값을 정하고, 중심값 기준으로 양옆으로 쿠키를 더해, 값이 같아지는 경우를 찾으면 되는 문제이다.
쿠키를 더하는 기준은, 두 쿠키의 누적합을 비교하여 적은 쪽 방향으로 쿠키를 더해야한다.

예를 들어보자.
cookie = [1, 1, 1, 1]

1 1 1 1
시작

for문을 cookie의 길이만큼 i라는 변수를 통해서 돌 것이다.
i는 당연히 0부터 len(cookie)-1까지 돌 것이다.

시작 기준은, 둘째가 가져가는 m+1 위치라고 정하는 것이 계산하기 편할 것이다.
그럼, 첫째가 가져가는 누적합과, 둘째가 가져가는 누적합을 계산해보자.
두 값이 초깃값은 0이다. 시작지점은 둘째가 가져가므로, 둘째의 누적합은 1이 된다.
다만, 첫째는 움직일 공간이 없으므로, 해당 경우는 답이 존재하지 않게된다.
i를 하나 올려보자.

1 1 1 1
시작

둘째가 1개를 먹고 시작한다.
그럼 첫째의 누적합이, 둘째보다 적으므로, 둘째쪽으로 하나 이동한다.

1 1 1 1
<- 시작

그럼, 첫째의 누적합이, 1이 늘어났다. 서로 같아졌다. 답을 저장해준다.
그 다음으로 두 값이 서로 같으므로, 첫째 또는 둘째 아무나 움직여본다.
둘째에 공간이 있으니, 둘째 쪽으로 한 칸 움직여 보겠다.

1 1 1 1
<- 시작 ->

둘째의 누적합이 2가 되었다. 첫째의 누적합이 더 적어졌으므로,
첫째도 이동한다. 그렇지만 갈 곳이 존재하지 않는다. 그럼 해당 경우에서는 1이 최댓값이 되겠다.
i를 한칸 더 움직여보자.

1 1 1 1
시작

둘째의 누적합이 1이고, 첫쨰의 누적합이 0이다. 첫째쪽으로 한 칸 움직여본다.

1 1 1 1
<- 시작

첫째와, 둘째의 누적합이 동일해졌다. 값을 저장하고, 둘 중 아무나 한 칸 이동한다. 둘째를 이동시켜보겠다.

1 1 1 1
<- 시작 ->

첫째의 누적합이 둘째보다. 적다. 첫째쪽으로 다시 한칸 이동한다.

1 1 1 1
<- <- 시작 ->

첫째와 둘쨰의 누적합이 같다. 값을 저장하고, 둘 중 아무나 한 칸 이동한다. 둘째를 이동시켜본다.
안된다. 이미 끝까지 이동했다. 그럼 최댓값인 2를 반환한다.

i를 계속 움직여보면서, 마저 해봐라. 아마 최댓값 2가 최대가 되는 것을 알 수 있다.
해당 로직은 while문을 사용하여, 간단하게 구현이 가능하다.
이 문제를 풀고 다른사람의 풀이를 보았는데, 누적합과, set자료형을 이용하여 간결하게 푼 사람도 존재했다.

최댓값이 sum(cookie)/2에 도달하였다면, 더 이상 그 위의 값은 나올 수 없으므로, 최댓값을 그냥 반환하면 된다.
효율성을 높일 수 있다.
만약 그렇지 않다면, 계속 끝까지 반복하여, 나온 최댓값을 산출해내면 된다.

이 문제는 "가장 긴 펠린드롬"과 상당히 유사한 문제이므로,
해당 문제를 풀어보았다면, 참고하여 풀면 도움이 될 것이다.

0 개의 답변
답변 쓰기
이 입력폼은 마크다운 문법을 지원합니다. 마크다운 가이드 를 참고하세요.