본문 바로가기
이것저것

동적계획법

by 문자메일 2018. 3. 22.

동적계획법

1. 일반적으로 최적화문제(optimision problem) 혹은 카운팅(counting) 문제에 적용됨

2. 주어진 문제에 대한 순환식(recurrence equation)을 정의한다.

3. 순환식을 memoization 혹은 bottom-up 방식으로 푼다.


알고리즘의 동작 방식

1. 문제를 부분 문제로 나눈다.

2. 가장 작은 부분 문제부터 해를 구한 뒤 테이블에 저장한다.

3. 테이블에 저장되어 있는 부분 문제의 해를 이용하여 점차적으로 상위 부분 문제의 최적해를 구한다.

 

subproblem들을 풀어서 원래 문제를 푸는 방식. 그런 의미에서 분할정복법과 공통성이 있다.

 

이 문제에 어떤 옵티멀 서브스트럭쳐(최적 부분해)가 존재하는가?

원래 문제의 부분 문제들의 해를 조합해서 원래 문제의 해를 어떻게 구할것인가?

이 문제에 대한 최적해의 한 부분이 그 부분에 대한 최적해인가?

 

int lcs(int m, int n)

{

for(int i=0; i<=m; I++)

    c[i][0] = 0;

for(int j=0; j<=n; j++)

    c[0][j] = 0;

for(int I=0; i<=m; I++){

for(int j=0; j<=n; j++)

{

if(x[i] == y[j])

c[i][j] = c[i-1][j-1]+1;

else

c[i][j] = Math.max(c[i-1][j], c[i][j-1]);

}

}

return c[m][n];

}


LCS 문제가 최적 부분 구조로 이루어져 있는지 확인 위한 점화식

1. 두 문자열중 하나라도 문자열 길이가 0이라면 0

2. 두 문자열의 마지막 부분이 같다면, TABLE[i, j] = TABLE[i-1, j-1]이 성립한다.

3. 두 문자열의 마지막 부분이 다르다면, TABLE[i, j] = MAX(TABLE[i-1, j],TABLE[i, j-1])


위 식을 바탕으로 알고리즘을 만든다면


아래는 풀 소스


#include <stdio.h>

#include <string.h>

#include <stdlib.h>


typedef struct structLCSTable

{

int** Data;

}LCSTable;


int LCS(char* X, char* Y, int i, int j, LCSTable* Table)

{

int m = 0; int n = 0;


/* 아무것도 없는 행을 표현하기 위하여 0으로 초기화 */

for (m = 0; m <= i; m++)

Table->Data[m][0] = 0;

for (n = 0; n <= j; n++)

Table->Data[0][n] = 0;


for (m = 1; m <= i; m++)

{

for (n = 1; n <= j; n++)

{

if (X[m - 1] == Y[n - 1])

{

Table->Data[m][n] = Table->Data[m - 1][n - 1] +1;

}

else

{

if (Table->Data[m][n - 1] >= Table->Data[m - 1][n])

Table->Data[m][n] = Table->Data[m][n - 1];

else

Table->Data[m][n] = Table->Data[m - 1][n];

}

}

}


return Table->Data[i][j];

}


void LCS_TraceBack(char* X, char* Y, int m, int n, LCSTable* Table, char* LCS)

{

if (m == 0 || n == 0)

return;


if (Table->Data[m][n] > Table->Data[m][n - 1] && Table->Data[m][n] > Table->Data[m - 1][n] && Table->Data[m][n] > Table->Data[m - 1][n - 1])

{

char TempLCS[100];

strcpy(TempLCS, LCS);

sprintf(LCS, "%c%s", X[m - 1], TempLCS);


LCS_TraceBack(X, Y, m - 1, n - 1, Table, LCS);

}

else if (Table->Data[m][n] > Table->Data[m - 1][n] && Table->Data[m][n] == Table->Data[m][n - 1])

{

LCS_TraceBack(X, Y, m, n - 1, Table, LCS);

}

else

{

LCS_TraceBack(X, Y, m - 1, n, Table, LCS);

}

}



void LCS_PrintTable(LCSTable* Table, char* X, char* Y, int LEN_X, int LEN_Y)

{

int i = 0; int j = 0;


printf("%4s", "");


for (i = 0; i < LEN_Y + 1; i++)

printf("%c ", Y[i]);

printf("\n");


for (i = 0; i < LEN_X + 1; i++)

{

if (i == 0)

printf("%2s", "");

else

printf("%-2c", X[i - 1]);


for (j = 0; j < LEN_Y + 1; j++)

{

printf("%d ", Table->Data[i][j]);

}


printf("\n");

}

}


int main(void)

{

char* X = "GOOD MORNING.";

char* Y = "GUTEN MORGEN.";

char* Result;


int LEN_X = strlen(X);

int LEN_Y = strlen(Y);


int i = 0;

int j = 0;

int Length = 0;


LCSTable Table;


Table.Data = (int**)malloc(sizeof(int*)* (LEN_X + 1));

for (i = 0; i < LEN_X + 1; i++)

{

Table.Data[i] = (int*)malloc(sizeof(int)* (LEN_Y + 1));


memset(Table.Data[i], 0, sizeof(int)* (LEN_Y + 1));

}


Length = LCS(X, Y, LEN_X, LEN_Y, &Table);


LCS_PrintTable(&Table, X, Y, LEN_X, LEN_Y);


Result = (char*)malloc(sizeof(Table.Data[LEN_X][LEN_Y] + 1));

sprintf(Result, "");

LCS_TraceBack(X, Y, LEN_X, LEN_Y, &Table, Result);


printf("\n");

printf("LCS:\"%s\" (Lenght : %d) \n", Result, Length);


return 0;

}



'이것저것' 카테고리의 다른 글

모의 SW 등산로 조성 소스  (0) 2018.03.24
SW 1226번 1227번 미로1, 2 [D4]  (0) 2018.03.23
그래프, DFS, BFS  (0) 2018.03.18
탐색 알고리즘  (0) 2018.03.14
정렬 알고리즘(퀵 정렬, 삽입 정렬, 계수 정렬)  (0) 2018.03.14

댓글