본문 바로가기
Algorithm/DP(동적 계획법)

[백준][1796번][DP] 신기한 키보드

by 우툴 2016. 3. 22.
728x90

신기한 키보드

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

<내가 푼 코드>

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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
#include <stdio.h>
 
int max(int a, int b){ return a > b ? a : b; }
int min(int a, int b){ return a > b ? b : a; }
int abs(int a){ return a > 0 ? a : -a; }
 
char lcdS[1001];
int totalmove = 10000000;
int alpaindex[26][2];
 
///////////////////////////////////////////////////////////////////////////////////
//
//        재귀를 통해서 완전 탐색을 한다
//    
//        입력 : 문자열 크기 , 지금 알파벳 , 현재 커서의 위치 , 지금까지 누른 타자 수
//
////////////////////////////////////////////////////////////////////////////////////
 
 
void allsimulate(int sizeint alpa, int preCusur , int totalcount){
 
    int maxindex = -1, minindex = 1100;
 
    if (totalcount > totalmove)
        return;
    if (alpa > 'z')
    {
        if (totalcount < totalmove)
        {
            totalmove = totalcount;
        }
        return;
    }
 
    maxindex = alpaindex[alpa - 'a'][0];
    minindex = alpaindex[alpa - 'a'][1];
 
    // 한 문자에 대해서 양 끝에 있는 것만 알면 됩니다.
 
    // 문자가 하나만 있을때
    if (maxindex == minindex){    
        allsimulate(size, alpa + 1, maxindex, totalcount + abs(preCusur - minindex) + abs(maxindex - minindex));
    }
    // 문자가 두개 이상 있을 때
    else if (maxindex != -1){
        allsimulate(size, alpa + 1, maxindex, totalcount + abs(preCusur - minindex) + abs(maxindex - minindex));
        allsimulate(size, alpa + 1, minindex, totalcount + abs(preCusur - maxindex) + abs(maxindex - minindex));
    }
    // 문자가 없을 때
    else{
        allsimulate(size, alpa + 1, preCusur, totalcount);
    }
}
 
int main(void){
 
 
    int size = 0;
    int preCusur = 0;
 
    // 문자열 입력을 받는다.
    scanf("%s", lcdS);
    while (lcdS[size!= 0)
        size++;
 
    // 각 문자에 대해서 양 끝에 대한 값을 찾아서 집어넣어준다.
    for (int alpah = 'a'; alpah <= 'z'; alpah++){
        int maxindex = -1, minindex = 1100;
        for (int i = 0; i < size; i++){
            if (lcdS[i] == alpah)
            {
                maxindex = max(i, maxindex);
                minindex = min(i, minindex);
            }
        }
        alpaindex[alpah - 'a'][0= maxindex;
        alpaindex[alpah - 'a'][1= minindex;
 
    }
 
    // 재귀 이용
    allsimulate(size'a', preCusur, 0);
    //엔터 입력 추가
    totalmove += size;
    
    printf("%d\n", totalmove);
    
 
    return 0;
}
cs


< 문제 푼 방법>

 1. 조건 엔터를 치는 경우는 생각을 안해도 된다 왜냐하면 n개 이기 때문이다.

 2. 같은 문자에서는 가장 양 끝의 것만 신경 써주면 된다.

 3. 현재의 커서를 알고 다음 알파벳의 양 끝의 index 값을 가지고 계산해준다. 

 4. 계산되어야 할 값은 같은 문자에서 양 끝의 이동 거리 그리고 다음 알파벳 양 끝으로가는 이동거리이다. 

 5. 그래서 이 경우의 수를 완전탐색 하는데 이 것을 재귀로 풀었다

     (1) 재귀의 탈출 조건 

- 이미 구해놓은 값보다 구하고 있는 값이 클 때 탈출 (왜냐하면 우리는 최소값만 알면 된다.)

- a~ z 까지 모든 탐색을 끝내면 그 값을 저장하고 탈출한다.

     (2) 재귀의 불러올 조건 

- 알파벳이 1개만 존재할 때

- 알파벳이 2개 이상 존재할 때

- 알파벳이 존재하지 않을 때

6. 재귀가 끝난다면 최소값이 구해진것을 볼 수 있다.

7. 다른 문제 풀이 방법으로는 DP로 푸는 방식이 있다고 한다. 

728x90

'Algorithm > DP(동적 계획법)' 카테고리의 다른 글

[백준][2293번][DP] 동전 1  (1) 2016.04.09
[ALGOSPOT][DP] PI  (1) 2016.04.06
[백준][1073번][DP] 도미노  (0) 2016.03.30
[백준][2092번][DP] 집합의 개수  (0) 2016.03.30
[백준][2169번][DP] 로봇 조종하기  (1) 2016.03.23

댓글