ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [백준] 17780번 새로운 게임
    문제 풀이 2020. 7. 31. 18:31

    17780 새로운 게임


    문제) https://www.acmicpc.net/problem/17780


    풀이)

    시뮬레이션 문제이다.


    선언한 자료들

    ① 말의 정보를 저장하는 구조체를 선언 & 정보 저장 배열 선언

    struct horse {

    int y, x, dir; // 말의 위치, 방향 

    };


    vector<horse> h_info;


    ② 체스판의 상태를 나타내는 int map[12][12]; 선언

    ③ 체스판의 위치에서, 가장 아래쪽에 있는 말 번호를 저장하는 int horse_map[12][12]; 선언


    만약 (1,1) 자리에 1 - 3 - 4번 순으로 말들이 쌓여있다면

    horse_map[1][1] = 1이다.


    ④ 각 말들이 업고? 있는 말 정보 저장하는 vector<int> parent[10]; 선언


    만약 1 - 3 - 4 순으로 말들이 쌓여있다면 -> 1번 말이 3번과 4번말을 업고 있다고 생각

    parent[1] = {1,3,4};

    parent[3]  empty

    parent[4]  empty 이다.


    위의 선언한 것들을 이용한 과정은 아래와 같다.


    1. 체스판의 상태와 말의 위치와 방향 입력받음

    2. 0번째 말부터 K-1번째 말 이동 시작(만약 i번째 말이 다른 말에게 업혀있는 상태(parent[i] empty)라면 pass)

      2.1 말이 이동할 위치가 흰색 칸일경우 : 그대로 이동. 

      2.2 말이 이동할 위치가 빨간색 칸일 경우 : 만약 여러 말들을 업고 있었다면 순서를 바꿔준 뒤 이동. 

      2.3 말이 이동할 위치가 map범위를 벗어나거나 파란색 칸일 경우 : 방향을 먼저 바꿈.

      바꾼 방향으로 이동할 위치 다시 확인

      그 위치가 흰색 칸이거나 빨간색 칸일 경우에만 이동.

    3. 각 말들이 업고있는 개수를 확인해 그 개수가 4이상이라면 횟수 출력

       (parent[i] >= 4?)

       4개 이상이 없다면 다시 2번으로 돌아감.



    +) 설명하기 어렵다.

        한 줄씩 디버깅하면서 본다면 이해하기 쉬울 것이다.


    코드)


    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
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    #include<stdio.h>
    #include<vector>
    using namespace std;
     
    struct horse {
        int y, x, dir;
        horse() {
            y = -1;
            x = -1;
            dir = 0;
        }
        horse(int y, int x, int dir) {
            this->= y;
            this->= x;
            this->dir = dir;
        }
    };
     
    int N, K;
    int result = -1;
    int map[12][12];
    int horse_map[12][12];
    vector<int> parent[10];
    vector<horse> h_info;
    bool suc = false;
    //방향 오른쪽 1 왼쪽 2 위쪽 3 아래쪽 4
    int dy[5= { 0,0,0,-1,1 };
    int dx[5= { 0,1,-1,0,0 };
     
    void move(int i) {
        int ny = h_info[i].y + dy[h_info[i].dir];
        int nx = h_info[i].x + dx[h_info[i].dir];
     
        //범위밖, 파란색 칸 : 방향 반대로 바꾸고 한칸이동
        if (ny < 0 || ny >= N || nx < 0 || nx >= N || map[ny][nx] == 2) {
            //방향 바꿈
            if (h_info[i].dir % 2 == 0) {
                h_info[i].dir -= 1;
            }
            else {
                h_info[i].dir += 1;
            }
            //바뀐 방향으로 이동할 칸 확인
            ny = h_info[i].y + dy[h_info[i].dir];
            nx = h_info[i].x + dx[h_info[i].dir];
            
            //방향을 반대로 한 후 이동하려는 칸이 파란색 또는 범위 밖을 벗어나는 곳이라면
            //방향만 바꿈.
            if (ny < 0 || ny >= N || nx < 0 || nx >= N || map[ny][nx] == 2return;
            
            //흰색칸 혹은 빨간칸일 경우 그 칸으로 이동
            move(i);
        }
        else if (map[ny][nx] == 0) {//흰색칸
        
            horse_map[h_info[i].y][h_info[i].x] = -1;//원래있던 칸 초기화 하고 이동
            for (int t = 0; t < parent[i].size(); t++) {//i번째 말이 업고 있는 말들의 위치도 바꿔줌
                h_info[parent[i][t]].y = ny;
                h_info[parent[i][t]].x = nx;
            }
            
            if (horse_map[ny][nx] != -1) {//이동할 칸에 누가 있다면
                for (int t = 0; t < parent[i].size(); t++) { //그 칸에 있는 말에게 다 업힘, 맨 위에 삽입
                    parent[horse_map[ny][nx]].push_back(parent[i][t]);
                }
     
                parent[i].clear();//새로운 칸의 말에게 모두 업혔으므로 초기화
            }
            else {//이동할 칸에 누가 없었다면, 그 칸의 주인이 됨
                horse_map[ny][nx] = i;
            }
        }
        else if (map[ny][nx] == 1) {//빨간색칸
     
            horse_map[h_info[i].y][h_info[i].x] = -1;
            for (int t = 0; t < parent[i].size(); t++) {
                h_info[parent[i][t]].y = ny;
                h_info[parent[i][t]].x = nx;
            }
            
            int new_leader = parent[i].back(); //맨 위에 업혀 있던 말이 맨 아래로 오게됨 
            if (new_leader != i) {//i번째 말이 다른 말들을 업고 있었다면 순서 뒤바꿈
                for (int t = parent[i].size() - 1; t >= 0; t--) {
                    parent[new_leader].push_back(parent[i][t]);
                }
                parent[i].clear();
            }
            
            if (horse_map[ny][nx] != -1) {//이동할 칸에 누가 있다면
                for (int t = 0; t < parent[new_leader].size(); t++) {
                    parent[horse_map[ny][nx]].push_back(parent[new_leader][t]);
                }
                parent[new_leader].clear();
            }
            else {
                horse_map[ny][nx] = new_leader;
            }
     
        }
     
    }
    int main() {
        scanf("%d %d"&N, &K);
        
        for (int i = 0; i < N; i++) {
            for (int j = 0; j < N; j++) {
                scanf("%d"&map[i][j]);
                horse_map[i][j] = -1;
            } 
        }
        for (int i = 0; i < K; i++) {
            int y, x, dir;
            scanf("%d %d %d"&y, &x, &dir);
            horse_map[y-1][x-1= i;
            h_info.push_back({ y-1,x-1,dir });
            parent[i].push_back(i);
        }
        int cnt = 1;
        
        while (cnt <= 1000 && suc == false)
        {
            //0번말부터 이동
            for (int i = 0; i < K; i++) {
                if (parent[i].empty()) continue;
                move(i);
            }
            for (int i = 0; i < K; i++) {
                if (parent[i].size() >= 4) {
                    suc = true;
                    result = cnt;
                    break;
                }
            }
            cnt++;
        }
        printf("%d", result);
        return 0;
    }
    cs


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

    [백준] 1202번 보석 도둑  (0) 2020.08.02
    [백준] 10986번 나머지 합  (0) 2020.08.01
    [백준] 6087번 레이저 통신  (0) 2020.07.30
    [백준] 9328번 열쇠  (0) 2020.07.29
    [백준] 5213번 과외맨  (0) 2020.07.28

    댓글

Designed by Tistory.