알고리즘/다이나믹2016. 9. 2. 15:12
반응형

정올 Q1871 줄세우기


▶ 문제 http://jungol.co.kr/bbs/board.php?bo_table=pbank&wr_id=1144&sca=3050


3 7 5 2 6 1 4

주어진 숫자를 최소한으로 이동하여 정렬하는 방법을 구하는 문제이다.

위 문제의 경우 7, 4, 1, 2를 옴겨 4번만에 정렬된 숫자열을 구할 수 있다.


▶ 문제 접근

 정렬알고리즘을 사용하여 문제를 푸는 것으로 접근하였다. 선택과 삽입중 고민하여 교환 횟수를 카운트하는 방법을 시도하였다. 여기에 다이나믹을 접목하여 f(n)의 n은 숫자으 갯수로 생각하여 문제에 접근하였다. 

하지만 f(n)들간의 관계를 정리하기 힘들었고 정렬의 특성상 최소한의 방법을 구하기 보다 각숫자를 삽입 교환하는 것 이하로 줄어들지 못하였다.


 문제 풀이

 다이나믹을 활용하면 의외로 쉽게 풀리는 문제이다.

 이 문제의 정렬되기전 주어진 순열에서 최대의 길이로 정렬된 순자의 열을 찾는 것이다. 

위 문제에서는 3, 5, 6 으로 정렬된 최대길이의 순자열이다. 이 숫자열 이외의 4개의 수를 이동하면 최소 이동 횟수를 구할 수 있다.

 이를 구하는 방법은 가장 높은탑 쌓기와 유사한 방법으로 구할 수 있다. 

가장 뒤에서 부터(위 문제의 숫자 4) 자기를 포함하여 오른쪽에 자기보다 큰 숫자중 최대길이를 가진 숫자를 찾는 것이다.

f(n)을 구해보자

f(6) = 1

f(6)(6번째 위치한 4를 뜻한다.)는 4보다 오른쪽에 위치한 숫자는 없으므로 자기 자신의 길이인 1이다.

f(5) = 2

오른쪽에 4가 있으며 1,4는 정상 순열이기에 1+f(6)이므로 2이다.

f(4) = 1, f(3) = 2, f(2) = 2, f(1) = 1, f(0) = 3이다. 

올바른 최대 길이의 순열은 3이므로 답은 7-3=4 가된다.



반응형

'알고리즘 > 다이나믹' 카테고리의 다른 글

정올 Q1407 숫자카드  (0) 2016.08.30
정올 Q2000 동전 교환  (0) 2016.08.28
정올 Q1539 가장 높은 탑 쌓기  (0) 2016.08.26
정올 Q1848 극장좌석  (0) 2016.08.26
정올 Q1491 자동차 경주 대회  (0) 2016.08.19
Posted by 조던발바닥
알고리즘/다이나믹2016. 8. 30. 15:44
반응형

정올 Q1407 숫자카드


 최근 연속해서 다이나믹 문제를 풀고 있다. 다이나믹 문제를 풀며 가장 중요한것은 어떤것을 기준으로 잡아 배열을 만들고 어떤방식으로 재활용하느냐 그것이 중요한 부분인것 같다. 문제를 풀며 다양한 형태의 다이나믹 문제 접근방식을 익혀가야겠다.


문제 : http://jungol.co.kr/bbs/board.php?bo_table=pbank&wr_id=683&sca=3050

 입력 받은 숫자열을 기반으로 숫자를 만들어 가능한 가짓수를 구하여라 1~34를 범위로 한다.


 

위그림과 같이 27123의 숫자가 주어졌을시 다음과 같이 6가지의 경우의 수를 완성할 수 있다. 

71의 경우 34보다 큰 수이므로 불가능하다.


▶ 문제 접근 방법(코딩 이전에 생각한 문제 접근방법)

 다이나믹형태로 문제에 접근하는 것을 기본으로 하여 생각해 보자. f(N)의 N을 무엇으로 설정할것인가 우선이 되어야한다. 2개의 숫자로 이루어진 카드의 갯수를 N으로 두고 문제에 접근해보겠다. 

 예를 들어 f(0)은 모두 1자리 숫자로 이루어진 숫자고 가짓수는 0이된다. 이러한 방식으로 접근해 보겠다. f(N)과 f(N-1....)간의 관계를 찾는 것이 우선되어야 할것이다.


▶ 문제 풀이

예상한 접근 방식엔 문제가 있었다. 기준이 애매했고 f(n)간의 점화식을 찾기에 힘들었다. 이 문제는 점화식문제에 가까웠다. 기본 알고리즘이후에 코드에 대한 설명을 하겠다.


f(N)을 먼저 구하는 것이 문제풀이의 시작으로 하였다. 여기서 N은 카드의 갯수이고 f(N)은 가능한 경우의 수이다. 

즉 f(1)은 1가지 카드로 조합가능한 가짓수를 뜻한다. 1가지만 가능하므로 1이다.

f(2)의 경우 1,2/12 2가지 방법이 가능하므로 2이다. f(3)은 3, f(4)는 5, f(5)는 8임을 알 수있다.

즉 f(N)=f(N-1)+f(N-2)의 식이 성립된다. 위 식이 나온것에 대해 설명해 보겠다.


예를 들어 f(4)은 1,2,3,4으로 이루어졌다고 가정하자.

(1~34의 조건은 나중에 생각하고 일단 경우의 수 부터 살펴 보자)


f(3)은 (1,2,3) / (12,3) / (1,23) 이고

f(4)는 (1,2,3,4),(1,2,34) / (12,3,4),(12,34) / (1,23,4) 5가지가 가능하다.


 123에 4를 넣는다고 생각해 보자.

 (1,2,3),(12,3)과 같이 마지막 숫자가 1개로 이루어진경우 경우의 수가 2배가 되는것을 볼수 있다. ex(1,2,3,4),(1,2,34) / (12,3),(12,3,4) 

 마지막 숫자가 1개로 이루어진 경우의 수는 n-2단계에서 올라온것이므로 f(n-2)와 같다는것을 알수 있다.

즉 f(n-2)*2가 된다.

 (1,23)과 같이 마지막 숫자가 2개로 이루어진 경우 갯수가 그대로 올라오는 것을 알수있다. 이것의 갯수는 n-1단계의 총갯수중 마지막숫자열이 2개로 이주어진 경우의수(n-2)를 뺀것이란 것을 알 수 있다.

즉 f(n-1)-f(n-2)가 된다. 

따라서  f(n) = f(n-1)-f(n-2)+f(n-2)*2가 되고 

다시 정리하면 f(n)=f(n-1)+f(n-2)라는 것을 알 수있다.


주어진 숫자에서 카드패로 만들수 없는 숫자가 나왔을시 자르고 각각의 경우의 수를 곱하는 방식으로 연산하였다.

즉 27123의 경우 

27 / 123 으로 나누고 2,7로 만들 수 있는 가짓수 f(2)=2

1,2,3으로 만들 수 있는 가짓수 f(3)=3 을 곱하여 6가지로 연산한다.

위의 7과 같이 4이상의 수가 자르는 index가 되며 0의 경우는 앞자리와 함께 비교하여 자를 포인트를 결정하게 된다. 또한 90,80과 같이 현재 위치가 0이고 앞 자리와 합한숫자가 34가 넘을경우 가짓수를 0으로 한다.



function 함수 속 if문을 보자

number.charAt(i)==48 && number.charAt(i-1)>51

현재 숫자가 0이고 앞 숫자가 4이상일때 40,50,60등의 숫자가 나타나므로 가능한 가짓수는 0개이다.

i+1==number.length()

마지막 숫자에 다달았을시 조건

number.charAt(i)==48

숫자가 0이었을시, 계산이 약간다르다 현재위치가 아닌 이전위치까지의 갯수를 세고 f(n)을 구한다.

number.charAt(i)>51 

숫자가 3보다 클 시


생각보다 까다로웠던 문제다 f(n)을 구하는 것부터 조건문을 작성하는 것까지 까다로웠다. 

반응형

'알고리즘 > 다이나믹' 카테고리의 다른 글

정올 Q1871 줄세우기  (2) 2016.09.02
정올 Q2000 동전 교환  (0) 2016.08.28
정올 Q1539 가장 높은 탑 쌓기  (0) 2016.08.26
정올 Q1848 극장좌석  (0) 2016.08.26
정올 Q1491 자동차 경주 대회  (0) 2016.08.19
Posted by 조던발바닥
알고리즘/다이나믹2016. 8. 28. 14:05
반응형

정올 Q2000 동전 교환


▶ 문제 : http://jungol.co.kr/bbs/board.php?bo_table=pbank&wr_id=1273&sca=3050

우리나라 동전의 단위는 1원, 5원, 10원, 50원, 100원, 500원의 6단계로 이루어진다. 잔돈 256원을 내주려면 500원 0개, 100원 2개, 50원 1개, 5원 1개, 1원 1개로 해서 모두 5개의 동전이 필요하다.


만약 동전 단위가 1원, 4원, 6원의 3단계로 이루어진 나라에서 8원을 내주려면 6원 1개, 1원 2개도 가능하고, 4원 2개로 가능하다. 앞의 경우에는 동전 3개, 뒤의 경우에는 동전이 2개 필요하다.


동전의 개수를 최소로 하면서 동전을 내주는 것이 목적이라면 뒤의 방법을 택해야 한다.

동전의 단위들이 주어지고, 원하는 잔돈이 주어질 때, 그 잔돈에 맞추기 위해 필요한 최소의 동전 수를 구하시오. 갖고 있는 동전의 수는 무한하다.


▶ 문제 접근

 일반적인 형태의 다이나믹 문제로 쉬운 편에 속한다.

 문제를 보면 점화 식 보다는 분할 정복 문제에 가깝다는 것을 알 수 있다.

다이나믹 문제에서 중요한 접근 방식은 N을 정하는 것이라 생각된다. 대부분의 경우 N은 기준이 되는 값이다. 이 문제의 N은 가격으로 설정하고 접근하였다.  즉 위 예제는 f(8)을 구하는 방법으로 문제에 접근하였다.



문제 풀이

1. N은 목표로 하는 가격이다. 코드 상에서 target 변수로 설정한다.

2. 분할 정복방식으로 f(1)부터 구해나간다.

3. 위 예제에서 사용 가능한 동전은 1, 4, 6이다.

f(1) = 1이 된다.

f(2)를 구하는 방법은 2번째 for문을 보자

coinList를 순환하면서 2-coin을 수행해본다.

1인 경우 2-1로 0보다 크고 f(1)의 값이 -1아니므로 if문에 적합하다.

(-1은 생성이 불가능한 숫자를 뜻한다 출력부분에서 -1인 경우 impossible을 출력하게 했다.)

따라서 f(1)값에 1개를 더 쌓은 갯수가 된다.

하지만 4, 6인경우 조건에 만족하지 않으므로 if문에 들어오지 않는다.


f(2) = 2;

f(3) = 3;

f(4) = 1;

f(5) = 2;

f(6) = 1;

f(7) = 2;

이렇게 단계별로 답이 나올 것이다.

f(8)의 경우

8-1=7, 8-4=4, 8-6=2가 된다

따라서 f(7), f(4), f(2)중 가장 작은 값에 1을 더 한 값이 f(8)이 된다.

f(8)은 2가 된다.




반응형

'알고리즘 > 다이나믹' 카테고리의 다른 글

정올 Q1871 줄세우기  (2) 2016.09.02
정올 Q1407 숫자카드  (0) 2016.08.30
정올 Q1539 가장 높은 탑 쌓기  (0) 2016.08.26
정올 Q1848 극장좌석  (0) 2016.08.26
정올 Q1491 자동차 경주 대회  (0) 2016.08.19
Posted by 조던발바닥
알고리즘/다이나믹2016. 8. 26. 20:36
반응형

정올 Q1539 가장 높은 탑 쌓기


문제 : http://jungol.co.kr/bbs/board.php?bo_table=pbank&wr_id=811&sca=305


가장 일반적인 형태의 다이나믹 프로그래밍 문제이다. 다이나믹 문제에서 유명한 knab과 유사한 형태를 띠고 있다.

조건

1. 넓이, 높이, 무게가 존재하며 동일 높이는 존재하나 동일 넓이, 무게는 없다.

2. 벽돌 위에 쌓으려면 넓이, 무게가 작아야 가능하다.

3. 가능한 모든 경우의 수중 최대 탑 높이를 구하여라


입력값



문제 접근

 최초 문제 접근 시 다이나믹 형태의 점화 식을 생각하지 못하였다. 그래서 각 벽돌과 그 벽돌 위에 쌓을 수 있는 벽돌을 찾아 2차원 int map을 만드는 형태로 코딩하였다. 답을 구할 수는 있었으나 다이나믹 문제 풀이의 의미가 없으므로 새로 접근해 보았다.

위에 올라갈 수 있는 벽돌의 수를 찾고 그 중 가장 높이가 높은 것과 자기 높이를 해서 자기의 값을 저장한다. 



문제 풀이

 1. 벽돌을 무게나 넓이에 의해 정렬한다.

위 입력 예시를 넓이에 의해 정렬해 보겠다.

1 5 2

4 4 6

9 2 3

16 2 5

25 3 4

편의상 위에서 순서대로 1번이라 칭하겠다.

1번벽돌 위에 올라갈 수 있는 벽돌은 존재하지 않는다 따라서 자기 높이만 더한 f(1)=5 이다.

2번 벽돌의 경우 1번 벽돌을 위에 올릴 수 있다. 따라서 최대 높이 f(2) = 9이다.

f(3)=7, f(4)=9, f(5)=10이다.

이중 최대 높이는 f(5)로 135번을 쌓은 것이다. 여기서 주의해야 할 점은 이 인덱스는 정렬한 상태이므로 초기 입력 시 받은 인덱스로 변환해 주어야 한다는 것이다.  생각보다 쉽게 풀리는 것이 다이나믹 문제라 할 수 있다.


다이나믹의 경우 N값이 보통 구하려고 하는 혹은 최대 값이 N인 경우가 대부분이다.

반응형

'알고리즘 > 다이나믹' 카테고리의 다른 글

정올 Q1871 줄세우기  (2) 2016.09.02
정올 Q1407 숫자카드  (0) 2016.08.30
정올 Q2000 동전 교환  (0) 2016.08.28
정올 Q1848 극장좌석  (0) 2016.08.26
정올 Q1491 자동차 경주 대회  (0) 2016.08.19
Posted by 조던발바닥
알고리즘/다이나믹2016. 8. 26. 10:58
반응형

정올 Q1848 극장좌석


▶ 문제: http://jungol.co.kr/bbs/board.php?bo_table=pbank&wr_id=1121&sca=3050


▶ 문제 조건

1. 본인으 좌석 좌,우에 앉을 수 있다.

2. 지정석은 본인만 앉아야 한다.

3. 좌석 갯수 N, 1 <= N, N <= 40

4. 고정석 갯수 M, 0<=M, M<=N

3. 좌석, 고정석이 주어질때 가능한 경우의 수를 구하여라.



 예시


▶ 문제 접근 방법(코딩 이전에 생각한 문제 접근방법)

 모든 경우의 수에 접근하는 것이 필요로 한다고 생각한다. DFS와 유사하게 스택을 사용하여 문제를 해결해 보려한다. 

 각 자리에서 가능한 수를 스택에 넣고 빼면서 수행하는 방식으로 접근해 보겠다.

-> 위 접근방법은 옳바르지 않다. 

물론 DFS를 사용해 가능한 가짓수를 돌며서 수행하여도 결과값은 찾을 수 있을 것이다. 하지만 다이나믹 알고리즘을 사용한다면 좀더 편리 하게 답에 도달 할 수 있었다. 문제풀이 만큼 접근방법이 중요한 부분이다.


▶ 문제 풀이

 다이나믹 문제로 접근하여 점화식을 사용하여 문제를 해결할 수 있다. 앞서 풀어본 분할 정복보다는 점화식에 가까운 문제로 판단 된다. 

점화식을 새우는 부분을 알아보자

f(N)은 N가지 좌석이 연속으로 주어졌을시 가능한 가짓수를 뜻한다.

(물론 지정석은 고려하지 않는다.) 


f(1)  = {1}                                                 1가지 

f(2) = {{1,2},{2,1}}                                        2가지

f(3) = {{1,2,3},{1,3,2},{2,1,3}}                             3가지

f(4) = {{1,2,3,4},{1,2,4,3},{1,3,2,4},{2,1,3,4},{2,1,4,3}}    5가지


위 가능한 가짓수의 형태를 보면 서로간의 관계가 있을을 알 수 있다. 

f(N)에서 가능한 가짓수들중 마지막 숫자가 N으로 끝나는 숫자열의 경우 

f(N+1)에서 2가지로 늘어나는 것을 확인할 수 있다.

즉 f(2)의 숫자열중 2로 끝나는 1,2는 f(3)에서 {1,2,3},{1,3,2}로 되지만

1로 끝나는 2,1은 f(3)에서 {2,1,3}만 가능하다.


그러면 마지막 숫자가 자기자신인 가짓수를 확인해면 f(n-1)고 같다는 것을 확인할 수 있다. ex(f(4)중 마지막 숫자가 4인 숫자열의 갯수는 3가지이다.) 이러한 이유는 쉽게 알 수 있다. x2된것중 반은 n-1로 끝나는 숫자일 것이고 나머지는 n으로 끝나는 것일 것이다. 

그러므로 4로 끝나는 숫자열의 갯수는 f(4-1)이다.


따라서 f(n) = f(n-2)X2+f(n-1)-f(n-2)인것을 알 수 있다. 

(f(n-1)-f(n-2)는 곱하지 않고 바로 올라온 가짓수이다.)

식을 정리해 보면 f(n) = f(n-2)+f(n-1)이 된다. 어쩌다 보니 피보나치 수열이 됬다....


문제로 다시 돌아가 보면 지정석 을 제외한 연속된 숫자열의 가짓수를 모두 찾고 그 값을 곱하면 답이 나온다. 

문제의 경우 123/4/56/7/89 이므로 f(3) X f(2) X f(2) = 12이다.








반응형

'알고리즘 > 다이나믹' 카테고리의 다른 글

정올 Q1871 줄세우기  (2) 2016.09.02
정올 Q1407 숫자카드  (0) 2016.08.30
정올 Q2000 동전 교환  (0) 2016.08.28
정올 Q1539 가장 높은 탑 쌓기  (0) 2016.08.26
정올 Q1491 자동차 경주 대회  (0) 2016.08.19
Posted by 조던발바닥
알고리즘/다이나믹2016. 8. 19. 09:07
반응형


정올 Q1492 자동차 경주 대회

고려사항

1. 한번에 최대 이동거리 제한

2. 이동 경로 추적 필요

3. 이동 카운트 계산 필요

문제 풀이

​다이나믹의 경우 점화 식을 세워 푸는 문제와 분할 정복 문제로 나뉜다고 느껴진다.

이 문제의 경우 후자에 속하며 f(0)부터 f(n)까지 각 포인트에서 최소 시간을 구하며 나가는 것이 문제를 해결하는 방법이라 생각한다.


내가 사용한 방법으로 설명해 본다.

f(0) = 0​

f(0)의 경우 start 포인트를 뜻한다. 최소 비용은 0이된다.

f(1) = 5

f(1)의 경우​ start에서 point 1 까지 가는 방법이 1가지 이므로 최소비용은 5.

f(2) = 10​

2가지 경우의 수가 존재한다. ​

1. 0에서 2까지 한번에 이동하는 경우(즉 f(0)+point2의 시간, 0+10=10)

2. 1에서 2까지 한번에 이동하는 경우(f(1)+point2의 시간, 5+10=15)​

1,2번의 경우에서 최소값을 구하고 f(2)에 넣는다. 2번이 최소값이 므로 ​f(2)=10

f(3) = 9

3가지 경우의 수가 존재한다.

1. 0에서 3까지 이동하는경우(f(0)+point3의 시간)

하지​만 1번의 경우 최대 이동거리를 초과한다. 100+30+100>140, 1번은 불가

2. 1에서 3까지 이동하는경우(f(1)+point3의 시간, 5+4=9)

3. 2에서 3까지 이동하는경우​(f(2)+point3의 시간, 10+4=14)

​2,3 번중 최소값을 구해 f(3)에 넣는다.

위와 같은 방식으로 마지막 위치까지 f를 구하면 최종위치에 도착하는 방법과 ​최소 시간을 구할 수 있다.

코드내 자세한 주석이 설명되어 있다.​


분할 정복 문제의 경우 작은 부분에서 각각을 채워나가며 구한다. 점화식을 필요로하는 다이나믹 문제보다 쉽게 느껴진다.

반응형

'알고리즘 > 다이나믹' 카테고리의 다른 글

정올 Q1871 줄세우기  (2) 2016.09.02
정올 Q1407 숫자카드  (0) 2016.08.30
정올 Q2000 동전 교환  (0) 2016.08.28
정올 Q1539 가장 높은 탑 쌓기  (0) 2016.08.26
정올 Q1848 극장좌석  (0) 2016.08.26
Posted by 조던발바닥
알고리즘/백트레킹2016. 8. 18. 15:47
반응형



정올 Q1824 스도쿠


문제 http://jungol.co.kr/bbs/board.php?bo_table=pbank&wr_id=1097&sca=3030



백트레킹


 백트레킹이란 단어가 어렵게 느껴질 수 있지만 간단하게 말하면 모든 경우의 수를 다 확인하는 것으로 더 효율적인 방법으로 수행하는 것이다. 대표적 예로 DFS가 있다. (DFS, BFS는 차후 다룰 것이다.)


 단계별로 수행과정을 살펴보자.

1. 한 단계를 변화시킬 경우의 수를 찾는다.

2. 그 중 한개를 선택한다.(순서는 임의로 선택한다.)

3. 선택된 경우에 수에서 1 단계와 마찬가지로 가능한 경우의 수를 찾는다.

4. 위처럼 1,2번을 번갈아 가며 수행하고 중간에 경우의 수를 찾지 못하였을때 이전 단계로 돌아가 다음 경우의 수를 수행한다. 


여기서 4번처럼 목표에 도달하지 못하였을때 이전 단계로 돌아가는 과정 때문에 백트레킹이라는 이름이 붙혔다고 생각된다. 위 단계가 이해되지 않는 다면 DFS를 공부해보는 것을 추천한다. 

 

 그리디 알고리즘의 경우 현재에서 최선을 판단해 수행하지만 그것이 항상 답이라는 것을 보장받기 힘들다 이에 반해 백트래킹의 경우 모든 경우의 수를 수행한다는 점에서 최선의 답을 도출할 수 있지만 속도가 느리다는 단점이 있다.




고려사항

1. 가로선에 1~9까지 숫자중 하나만 들어간다.

2. 세로선에 1~9까지 숫자중 하나만 들어간다.

3. 사각형 안에 1~9까지 숫자중 하나만 들어간다.

4. 모두 0인경우가 존재할 수 있다.


문제 풀이




DFS는 스택을 사용하지만 스택 대신 재귀함수를 사용하여 문제를 해결하였다. 재귀도 스택도 같은 모양이니 편한데로 푸는것이 좋을듯 하다.


1. 입력을 받으며 빈곳의 위치를 배열에 저장한다. 

 위 맵의 경우 (0,0), (1,4), (1,7), (2,0)....이 저장될 것이다.

2. 배열에 저장된 순서대로 경우의 수를 확인한다.


2-1 (0,0)에 들어갈 수 있는 수를 확인한다. [1] 가능

2-2 (1,4)에 들어갈 수 있는 수를 확인한다. [3] 가능

.

.

.

3. 경우의 수가 2개 이상인경우 순서대로 실행한다.

4. 경우의 수가 없는 경우 이전단계로 돌아가 다음 경우의 수를 선택한다. Stack이나 재귀를 통해 가능







 



반응형
Posted by 조던발바닥