ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [SWEA] 5656 벽돌깨기
    문제 풀이 2020. 5. 14. 22:04

    5656 벽돌깨기


    풀이)

    모든 경우를 확인해보는 문제였다.


    처음에 

    없애는 벽돌에 적힌 숫자만큼이나 상하좌우 다른 벽돌을 제거하는 걸 어떻게 처리할까 싶었는데

    그냥 벽돌에 적힌 수만큼 상하좌우 모두 방문 해보고 바꿔주면 되었다.

    -> 다 방문한다!!


    간단히 풀이과정을 말해보자면


    1. dfs을 통해 어떤 행의 벽돌을 없앨 건지, 행들의 순열(n개 길이)을 구한다.

    2. 그 순열 순서대로 벽돌을 없애고, 벽돌을 내리는 행위를 반복한다.

      -> 벽돌없애는 과정도 dfs를 통해 없앤다.


    벽돌을 없애는 함수는  -> change()

    벽돌을 내리는 함수는 -> relocate()


    주의할 점

    재귀 방법을 이용해서 벽돌을 없애므로, 이전 상태의 값을 저장해놓고

    되돌아 왔을 때 원래 값으로 다시 바꿔줘야한다는 점이다.


    코드)


    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
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    #include <stdio.h>
    #include <algorithm>
    #include <vector>
    using namespace std;
     
    #define INF 999999999
     
    int n, w, h;
    vector <vector<int>> map;
     
    int result;
    int dy[4= { -1,1,0,0 };
    int dx[4= { 0,0,-1,1 };
     
    bool check_range(int y, int x) {
        if (x >= 0 && y >= 0 && x < w && y < h)
            return true;
        else
            return false;
    }
     
    void change(int y, int x) {
        if (!check_range(y, x))return;
        if (map[y][x] == 0return;
     
        int len = map[y][x];
        map[y][x] = 0;
        
        for (int i = 1; i < len; i++//벽돌에 적힌 수만큼 상하좌우 모두 이동
        {
            for (int j = 0; j < 4; j++)//상하좌우
            {
                int ny = y + dy[j] * i;
                int nx = x + dx[j] * i;
                
                if (check_range(ny, nx) && map[ny][nx] != 0)
                    change(ny, nx);
            }
        }
    }
     
    void relocate() {
        for (int i = 0; i < w; i++) {
            for (int j = h - 1; j >= 1; j--) {
                for (int k = j - 1; k >= 0; k--) {
                    if (map[j][i] != 0break;
                    if (map[k][i] != 0) {
                        map[j][i] = map[k][i];
                        map[k][i] = 0;
                        break;
                    }
                }
            }
        }
    }
     
     
    void dfs(int depth) {
        
        if (depth == n) {
            int cnt = 0;
            for (int i = 0; i < h; i++) {
                for (int j = 0; j < w; j++) {
                    if (map[i][j] > 0) cnt++;
                }
            }
            result = min(result, cnt);
            return;
        }
     
        vector <vector<int>> temp = map;//상태 저장
        for (int i = 0; i < w; i++) {
            int y = 0;
            while (check_range(y, i)&&map[y][i] == 0)
            {
                y++;
            }
            change(y,i); //i번째 행의 벽돌 깨기 
            relocate(); // 벽돌 떨굼
            dfs(depth + 1);
     
            //원래값으로 돌려놓음
            map = temp;
        }
    }
     
    int main() {
        //freopen("sample_input (1).txt""r", stdin);
        int T = 0;
        scanf("%d"&T);
        map.resize(15);
        for (int i = 0; i < 15; i++) {
            map[i].resize(12);
        }
        for (int test_case = 1; test_case <= T; test_case++) {
            result = INF;
            scanf("%d %d %d"&n, &w, &h);
            for (int i = 0; i < h; i++) {
                for (int j = 0; j < w; j++) {
                    scanf("%d"&map[i][j]);
                }
            }
            dfs(0);
            printf("#%d %d\n", test_case, result);
        }
        return 0;
    }
    cs


    '문제 풀이' 카테고리의 다른 글

    [프로그래머스] 가장 큰수  (0) 2020.05.16
    [프로그래머스] 여행경로  (0) 2020.05.15
    [SWEA] 4012 요리사  (0) 2020.05.13
    [SWEA] 5650 핀볼게임  (0) 2020.05.12
    [SWEZ] 2383 점심 식사시간  (0) 2020.05.11

    댓글

Designed by Tistory.