백준 1248 맞춰봐
본문 바로가기
알고리즘 모음집/알고리즘 (Algorithm)

백준 1248 맞춰봐

by KyeongMin 2019. 7. 23.
728x90
반응형

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

 

1248번: 맞춰봐

문제 규현이는 멍청하다. 왜냐하면, 1~10까지 수 밖에 모르기 때문이다. 어느 날 규현이 옆을 지나가던 태석이가 규현이를 보고 이렇게 외쳤다. "빵빵!!" 규현이는 "아하!" 하면서 세상에는 빵이란 수도 있구나 했다. 그날 이후로 규현이는 매일 친구들을 볼 때면 "빵빵!!" 거리면서 인사를 했다. 규현이의 친구 중에는 태방이가 있다. 자꾸 규현이가 "빵빵!!" 거릴때 마다 자신을 놀리는 것 처럼 생각했던 태방이는 규현이에게 그건 "빵이 아니고 영이야"

www.acmicpc.net

문제의 본문을 읽으면서 문제를 장난으로 냈나? 생각할 정도로 이전에 문제와는 대화형이 많은 내용이였다 결국은 

위의 80%정도가 대화였고 나머지 20 %정도가 실제 문제 풀이를 위한 설명이였던것 같습니다.

결론적으로 

입력을 보면

4

- + 0 + + + + - - + 

주어지는데 

 

1 2 3 4

0 5 6 7

0 0 8 9

0 0 0 10

저렇게 입력이 4가 들어오는 경우 이차원 배열에 

4개의 수의 합이 들어가게 되는데 

출력을 보면 

Arr 배열 

Arr[0] = -2, Arr[1] = 5, Arr[2] = -3, Arr[3] = 1 

이라면 

예를 들어 0,2라면 Arr[0]+ Arr[1] + Arr[2] 를 더한다는 의미 이므로 아래와 같이

배열 0, 0 은 1번에 더해지는 것으로   Arr[0] 인                        -2 = -2             이므로 - 가 되고

배열 0, 1 은 2번에 더해지는 것으로   Arr[0] + Arr[1]                 -2 + 5 = 3        이므로 + 가되고

배열 0, 2 는 3번에 더해지는 것으로   Arr[0] + Arr[1] + Arr[2]      -2 + 5 + -3 = 0 이므로 0 이 됩니다.

 

배열 1, 1 은 4번에 더해지는 것으로   Arr[1] 인                         5 = 5              이므로 + 가 됩니다.

이런식으로 

각 이차원 배열의 y와x가 있을때 y 부터 x 까지 의 숫자를 인덱스로 가지는 배열의 합이 들어가는 것 입니다.

그렇게 처음에 저는 구현할때 입력을 받고 위의 이차원 배열에 입력으로 주어지는 - + 0 을 먼저 넣었습니다.

 

그리고 나서 재귀를 이용하여 백트래킹을 하였습니다. 

이유는 -10 ~ 0 ~ 10 까지 주어진 수였고 그것이 겹치는것이 없이 모든 경우를 보기 위해서 선택했습니다.

 

설명이 길어진것 같은데 그냥 단순히 N 4라면 4개의 배열에 숫자를 전부 다 넣어보면 시간초과가 날수 있기때문에

배열에 숫자를 넣기전에 chk() 함수를 구현하여 위의 계산식에 근거하여 0번배열에는 -값이 들어갈수 있도록 하여

경우를 줄여서 시간초과를 해결했습니다.

 

익숙해진다고 생각을 했던 백트래킹이였지만 아직까지도 조금 한부분이 아직 완벽히 채워지지 않아서

실망스러웠지만 앞으로는 실수하지 않도록 할것이라고 다짐했습니다.

 

아래 소스를 보시고 이해를 하시면 더 쉽습니다.

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
#include<stdio.h>
#include<stdlib.h>
int N;
int ret;
int num[10];
char result[56];
char cc[56][56= { 0, };
bool chk(int idx) {
    int cdx = 0;
    int sum = 0;
    for (int i = 0; i <= idx; i++) {
        int sum = 0;
        for (int j = i; j <= idx; j++) {
            sum += num[j];
            char a;
            if (sum < 0)a = '-';
            if (sum == 0)a = '0';
            if (sum > 0)a = '+';
            if (a != cc[i][j]) {
                return 0;
            }
        }
    }
    return 1;
}
void dfs(int idx) {
    if (idx == N) {
        int cdx = 0;
        //if (chk(N-1) == 0) return;
        for (int i = 0; i < N; i++) {
            printf("%d ", num[i]);
        }
        //printf("\n");
        //return;
        exit(0);
    }
    //chk(idx);// 가지치기
    for (int y = -10; y <= 10; y++) {
        num[idx] = y;
        if (chk(idx)) {
            dfs(idx + 1);
        }
        num[idx] = 0;
    }
}
 
int main(void)
{
    scanf("%d"&N);
    scanf("%s", result);
    int idx = 0;
    for (int i = 0; i < N; i++) {
        for (int j = i; j < N; j++) {
            cc[i][j] = result[idx++];
        }
    }
    dfs(0);
    return 0;
}
 
 

오늘은 여기까지이고 항상 모든 경우를 보려고 하지말고 가지를 칠것을 치도록 해야한다는 것을 배우게 되었고 

여러가지로 접근하는법이 많구나 느꼈습니다.

보시느라 고생 많으셨습니다. 감사합니다.

728x90
반응형

'알고리즘 모음집 > 알고리즘 (Algorithm)' 카테고리의 다른 글

백준 6603 로또  (0) 2019.07.24
백준 1339 단어 수학  (0) 2019.07.23
백준 10819 차이를 최대로  (0) 2019.07.23
백준 10973 이전 순열  (0) 2019.07.23
백준 10972 다음 순열  (0) 2019.07.23

댓글