ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [백준] 10472번 십자뒤집기
    문제 풀이 2020. 3. 24. 02:36

    10472 십자뒤집기


    문제


    당신에게 3x3 크기의 보드가 주어진다. 각각의 칸은 처음에 흰색 혹은 검은색이다. 만약 당신이 어떤 칸을 클릭한다면 당신이 클릭한 칸과 그 칸에 인접한 동서남북 네 칸이 (존재한다면) 검은색에서 흰색으로, 혹은 흰색에서 검은색으로 변할 것이다.

    당신은 모든 칸이 흰색인 3x3 보드를 입력으로 주어지는 보드의 형태로 바꾸려고 한다. 보드를 회전시킬수는 없다.

    Figure D.1: 예제 입력

    입력


    첫 줄에는 테스트 케이스의 숫자 P(0 < P ≤ 50)이 주어진다.

    각각의 테스트 케이스에 대해서 세 줄에 걸쳐 한 줄에 세 글자씩이 입력으로 들어온다. "*"은 검은색을 뜻하며 "."은 흰색을 뜻한다.


    출력


    각각의 테스트 케이스에 대해서 흰 보드를 입력에 주어진 보드로 바꾸는 데 필요한 최소 클릭의 횟수를 구하여라.



    풀이) 


    bfs와 set을 이용해 결과가 나올때까지 탐색해서 푼 문제이다. 

    예전에 풀었던 주사위 회전 문제랑 비슷한것 같다.

    3x3 보드를 9개의 원소를 가지는 배열로 만든다고 생각해보자.

    칸이 칠해진 경우를 1, 칠해지지 않은 경우를 0이라고 할때 

    나타날 수 있는 보드의 상태 개수 2^9개이다.


     0

    1

     2

     3

    4

     5

     6

    7

     8


     0

     2

     3

     4

     5

     6

     7

     8


    0이 뒤집어지면 → 1와 3도 뒤집어져야함

    1가 뒤집어지면 → 0과 2, 4가 뒤집어져야함

    ...

    7이 뒤집어지면 → 4, 6, 8이 뒤집어져야함

    이런식으로 생각하고 풀었다. 


    또한, 배열의 상태를 queue에 넣기 힘들므로 string으로 바꿔서 처리하였고 반복하지 않기 위해 set을 통해 중복되는 상태는 걸렀다.


    코드)

    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
    #include <stdio.h>
    #include<queue>
    #include <string>
    #include <set>
    #include <vector>
    using namespace std;
     
    //각 칸을 누를 때 뒤집힐 칸들(자기 자신도 포함해서)
    vector <int> vec[9= {
        {013}, {0124}, {1,25},
        {0346}, {13,457}, {2458},
        {367}, {46,78}, {57,8}
    };
     
    int bfs(string s) {
        queue<string> qu;
        set<string> check;
        qu.push("000000000");
        check.insert("000000000");
        int time = 1;
        while (!qu.empty())
        {
            int size = qu.size();
            while (size--)
            {
                string here = qu.front();
                qu.pop();
                for (int i = 0; i < 9; i++) {
                    string next = here;
                    for (int j = 0; j < vec[i].size(); j++) {
    //뒤집어 주는 과정
                        if (next[vec[i][j]] == '1') {
                            next[vec[i][j]] = '0';
                        }
                        else {
                            next[vec[i][j]] = '1';
                        }
                    }
                    if (check.find(next) != check.end()) continue;
                    if (s == next) return time;
                    qu.push(next);
                    check.insert(next);
                }
            }
            time++;
        }
    }
     
    int main() {
        int test_case;
        scanf("%d"&test_case);
        getchar();
        while (test_case--)
        {
            string st = "";
            int idx = 1;
            for (int i = 0; i < 3; i++) {
                for (int j = 0; j < 3; j++) {
                    char ch;
                    scanf("%c"&ch);
                    if (ch == '*') {
                        st += "1";
                    }
                    else {
                        st += "0";
                    }
                    idx++;
                }
                getchar();
            }
            if (st == "000000000"printf("0\n");
            else {
                printf("%d\n", bfs(st));
            }
        }
        return 0;
    }

    cs


    결과) 


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

    [백준] 1315번 RPG  (0) 2020.03.24
    [백준] 17882번  (0) 2020.03.24
    [백준] 2234번  (0) 2020.03.23
    [백준] 2293번  (0) 2020.03.21
    [백준] 2579번  (0) 2020.03.21

    댓글

Designed by Tistory.