https://www.acmicpc.net/problem/11726

 

11726번: 2×n 타일링

2×n 크기의 직사각형을 1×2, 2×1 타일로 채우는 방법의 수를 구하는 프로그램을 작성하시오. 아래 그림은 2×5 크기의 직사각형을 채운 한 가지 방법의 예이다.

www.acmicpc.net

이 문제는 앞에서 포스트 했던 '이친수' 문제와 상당히 유사합니다. 

경우의 수를 나열해 보아도 쉽게 규칙이 보이지만, 이론적으로 생각해 보아도 쉽게 규칙을 발견할 수 있습니다. 

 

위 그림은 i = 5 일 때의 예시입니다. 

따라서 이와 같은 알고리즘을 코드로 구현하면 쉽게 풀이가 가능합니다. 

 

https://www.acmicpc.net/problem/15664

 

15664번: N과 M (10)

한 줄에 하나씩 문제의 조건을 만족하는 수열을 출력한다. 중복되는 수열을 여러 번 출력하면 안되며, 각 수열은 공백으로 구분해서 출력해야 한다. 수열은 사전 순으로 증가하는 순서로 출력해

www.acmicpc.net

유명한 N과 M 시리즈이다. 

이 문제는 앞에서 포스트한 N과 M(8)번 문제의 연장선이다.

이 문제에서 중요한건 dfs를 이용하여 필요한 경우의 수를 탐색한 후 결과값으로 출력하는 것이다 

 

즉, 핵심 알고리즘 부분은 for문에서 index 범위를 지정하여 탐색하는 부분이라 할 수 있다. 

우선 코드는 다음과 같다. 

 

앞서 포스트한 N & M(8)서는

solve(level+1, idx) -> 탐색을 하고 해당 idx를 넘어가지 않고 그대로 input으로 두어 탐색할 수 있게 하였다면 

이번 포스트에서는 solve(level+1,idx+1) 로 지정하여 한번 탐색한 경우는 다시 고려하지 않고 넘어가는 식으로 구현하는것이 차이라고 볼 수 있다. 처음에 풀때 input 문자열을 굳이 int형으로 지정하여 문제를 풀었었는데 그럴필요없이 str 자료형으로 문제를 해결하면 될듯하다. 

https://www.acmicpc.net/problem/2193

 

2193번: 이친수

0과 1로만 이루어진 수를 이진수라 한다. 이러한 이진수 중 특별한 성질을 갖는 것들이 있는데, 이들을 이친수(pinary number)라 한다. 이친수는 다음의 성질을 만족한다. 이친수는 0으로 시작하지 않

www.acmicpc.net

이 문제는 '타일' 문제와 비슷하다 

시작은 무조건 1로 시작해야하며, 11이 두 번 연속으로 나타나지 않는 이진수를 찾는 문제이다.

그냥 경우의 수를 나열해 봐도 쉽게 규칙을 찾을 수 있지만 

조금만 생각해보면 알고리즘을 금방 생각할 수 있다. 

만약 4자리 이친수의 갯수를 찾는다하면 (dp[4]라고 하자) 

 

dp[3](3자리 이친수) 에다 마지막에 '0'을 하나 붙여도 이친수를 만족하며

dp[2](2자리 이친수) 에다 앞에 '10'을 붙여도 위 두 조건을 만족한다 

따라서 규칙은 dp[i] = dp[i-1]+dp[i-2]임을 알 수 있다. 

 

코드는 아래와 같다.

 

 

https://www.acmicpc.net/problem/8595

 

8595번: 히든 넘버

문제 단어에 숫자가 숨어있다. 이 숫자를 히든 넘버라고 한다. 알파벳 대/소문자와 숫자로 이루어진 단어가 주어졌을 때, 모든 히든 넘버의 합을 구하는 프로그램을 작성하시오. 단어와 히든 넘�

www.acmicpc.net

이 문제는 사실 알고리즘이 특별하다기보다 구현하는데 있어서 조금 생각이 필요했던 문제였습니다. 

어설프게 for문을 여러번 돌릴경우에 시간초과가 나기 때문에, 주어진 문자열을 for문 한번에 돌려 

해답을 찾아내는 구현을 하는것이 관건입니다.

 

이를 위해서 앞에서 부터 문자열을 탐색하는 것이 아닌 뒤에서 부터 문자열을 탐색하여

숫자가 하나씩 나올 때마다 (자리수) * 해당숫자, 즉 처음 나온 숫자라면 1*(해당 숫자) 

두번째 연속으로 나온 숫자라면 10*(해당숫자), 이런 식으로 탐색하여 더해주는것이 해답입니다. 

코드는 아래와 같습니다.

 

https://www.acmicpc.net/problem/15657

 

15657번: N과 M (8)

N개의 자연수와 자연수 M이 주어졌을 때, 아래 조건을 만족하는 길이가 M인 수열을 모두 구하는 프로그램을 작성하시오. N개의 자연수는 모두 다른 수이다. N개의 자연수 중에서 M개를 고른 수열 �

www.acmicpc.net

이번 문제는 장장 1시간 가까이 삽질을 한 문제입니다.. 

알고리즘 자체는 dfs를 잘 알고 있다면 무난하게 풀 수 있는 문제입니다. 

  • N개의 자연수 중에서 M개를 고른 수열
  • 같은 수를 여러 번 골라도 된다.
  • 고른 수열은 비내림차순이어야 한다.
    • 길이가 K인 수열 A가 A1 ≤ A2 ≤ ... ≤ AK-1 ≤ AK를 만족하면, 비내림차순이라고 한다

이 3가지 조건중에서 3번째 조건은 맨처음 받은 입력을 정렬만 해주면 해결되는 문제이고,

첫번째 M개를 고른다는 조건은 dfs에서 level M 까지 탐색하고 종료한다는 뜻 

두번 째 같은 수를 여러 번 골라도 된다 라는 조건은 알고리즘 적인 코딩을 통해 해결할 수 있습니다. 

그에 따라 작성한  코드는 다음과 같습니다. (주의!  틀린부분이 있습니다.)  

 

위에서 틀린 부분 눈치채셨나요?

이 코드를 작성할 때 입력을 한자리수 숫자로 가정하고 작성하였습니다.. 

한자리 수일 때는 문제가 없지만 만약 숫자가 한자리수 이상일 경우에는 

문자열로 받을경우 1234 -> '1','2','3','4' 로 받게 되기 때문에 기존의 생각한 것과 다른결과를 얻게됩니다..

저는 이 부분을 생각을 못해 1시간 동안 오류를 찾는데 시간을 보냈습니다..

수정한 코드는 아래와 같습니다. 

 

https://www.acmicpc.net/problem/1937

 

1937번: 욕심쟁이 판다

n*n의 크기의 대나무 숲이 있다. 욕심쟁이 판다는 어떤 지역에서 대나무를 먹기 시작한다. 그리고 그 곳의 대나무를 다 먹어 치우면 상, 하, 좌, 우 중 한 곳으로 이동을 한다. 그리고 또 그곳에서

www.acmicpc.net

이번 문제는 구현을 생각하는데 있어서 까다로웠던 문제였습니다. 

일단 그래프를 탐색하는데 있어서 dfs를 재귀적으로 구현, 또 탐색에 조건문을 달고, dp의 메모이제이션을 이용하여 연산 케이스 감소 등 3개의 콤비네이션을 이용한 구현이 필요했는데요.. 처음 구상한 주도 코드는 다음과 같습니다

어차피 조건에 항상 더 큰 숫자가 있는곳으로만 이동한다 하였으니, 다시 같은곳으로 되돌아오게될 경우를 

체크할 필요는 없습니다. 다만 문제에 주어진 조건을 잘 정의하고, 해당하지 않는경우는 pass, 

그리고 dfs로 탐색하게 될경우 재귀적으로 반환값을 받아 차례대로 각 이동경로마다의 best값을 설정하게 해주는 부분이 생각하기 까다로웠던것 같습니다.  

 

위 주도코드를 기반으로 작성한 코드는 다음과 같습니다. 

 

 

여기에서 중요한 부분은 sys.setrecursionlimit(1000000) 를 선언해주는 것이었는데요..

파이썬에서는 재귀적 탐색할 경우 탐색할 수 있는 깊이가 제한되어있어서 이렇게 리미트를 해제해야 합니다 

또한 dp[i][j]가 기본적으로 어떠한 값이 설정되어있다면, 그 값을 return하게 하여 불필요한 탐색경우를 줄였습니다. 

이상으로 욕심쟁이 판다 포스트를 마치겠습니다. 

https://www.acmicpc.net/problem/1912

 

1912번: 연속합

첫째 줄에 정수 n(1 ≤ n ≤ 100,000)이 주어지고 둘째 줄에는 n개의 정수로 이루어진 수열이 주어진다. 수는 -1,000보다 크거나 같고, 1,000보다 작거나 같은 정수이다.

www.acmicpc.net

dp문제는 일단 배열에 적어가다보면 해결방법이 보이는것 같습니다. 

 

우선 위 검은색 글자가 주어진 수열이며, 빨간색이 갱신되는 dp 배열에 들어갈 요소입니다. 

최고값만 찾으면 되므로 일단은 다 더해본 후 그중 최고의 값을 찾으면 됩니다. 

 

다만 한가지 규칙이 있는데요 바로 dp[i]와 그 다음 i+1번째의 숫자요소를 더해 본 후 

그값이 i+1번째 숫자요소보다 작을경우는 dp[i+1]번째 값을 i+1번째 숫자요소로 갱신합니다. 

 

왜냐하면 dp[i]와 num[i+1]이 그냥 기존의 num[i+1]값보다 작게된다면, 

num[i+1]부터 숫자를 더해가는것이 기존의 값을 이어가는 것 보다 더 크기 떄문입니다. 

따라서 이와같은 규칙을 염두하여 코드를 작성하면 다음과 같이 간단히 짤 수 있습니다. 

 

https://www.acmicpc.net/problem/2163

 

2163번: 초콜릿 자르기

정화는 N×M 크기의 초콜릿을 하나 가지고 있다. 초콜릿은 금이 가 있는 모양을 하고 있으며, 그 금에 의해 N×M개의 조각으로 나눠질 수 있다. 초콜릿의 크기가 너무 크다고 생각한 그녀는 초콜릿�

www.acmicpc.net

이 문제는 dp 문제로 굉장히 쉬운 문제입니다. 

복잡하게 생각할 필요없이 배열에 수를 채워나가다 보면 규칙이 보이는 문제인데요

먼저 임의의 NxM의 배열에 대해서 쪼개는 갯수를 다음과 같이 채워넣어봅시다.

4x5 사이즈 초콜릿 쪼개기 횟수

규칙은 한눈에 봐도 알수 있을만큼 단순합니다.

즉 첫번째 열의 N번째 요소에 대해서  x m +(m-1)을 수행한다면

(i,m) 번째 요소를 구할 수 있습니다. 즉 우리가 필요한 것은 (5,4), 즉 (m,n)의 요소이므로 

(1,m)*m+m-1을 계산하면 답을 구할 수 있겠네요, 따라서 코드를 작성하면 다음과 같습니다. 

 

+ Recent posts