본문 바로가기
알고리즘

백준 3190 뱀 (c++)

by kcj3054 2021. 12. 20.

문제

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

주의

  • 풀어 봤던 문제를 복기할려고 했는데 먼가 꼬였다. 로직은 틀린게 없었다. 문제를 제대로 안읽어서 그랬다.

  • 문제에서 뱀의 머리를 먼저 늘려서 다음칸 이동 -> 이동한 칸에 사과가 있으면 사과 없어지고 꼬리를 지우지 않는다였는데 여기서 풀 때 꼬리를 먼저 지우고 머리를 이동시켜버렸다,

  • 뱀의 머리위치, 몸의위치, 꼬리 위치를 다 편안하게 관리하기 위해서 vector를 사용했다, dequeue를 사용해도되는데 vector의 insert만으로도 충분했다.

  • 뱀이 꼬인 부부의 소스는 뱀의 머리가 몸통 중에서 하나랑 부딪쳤는지 확인 하는 것이다. 그래서 머리를 빼고, for 순회를 Snake의 1부터 시작하면된다.

  • 문제에서 '먼저 뱀은 몸길이를 늘려 머리를 다음칸에 위치시킨다.'라고 적혀있기에 머리를 늘리는 순간 다음에 바로 몸이 꼬인지를 확인해야한다.

  • 또한 Info의 정보를 확인할 때 '게임 시작 시간으로부터 X초가 끝난 뒤에 왼쪽(C가 'L') 또는~', 여기서 X초가 끝난 뒤라고 적혀있으니 해당 초의 마지막에 방향 전환 로직을 실행하면된다.

    소스

#include <bits/stdc++.h>

using namespace std;


//맨 처음 방향으 오른쪽이다 
// 크기 n, 사과의 개수 k, 
int n, k, L, Time, dir;
int grid[200][200];
int dirMapper[200];
vector<pair<int, int>> Snake;
vector<pair<int, int>> Info;
int dx[] = { -1, 0, 1, 0 };
int dy[] = { 0, 1, 0, -1 };


void Print() {
    cout << "뱀 위치 출력=====================" << endl;
    for (int i = 0; i < Snake.size(); i++)
    {
        cout << Snake[i].first << " " << Snake[i].second << endl;
    }
    cout << "=============종료=============" << endl;
}

bool InRange(int x, int y) {
    return x >= 1 && x <= n && y >= 1 && y <= n;
}

bool isTwist() {

    pair<int, int> head = Snake[0];
    for (int i = 1; i < (int)Snake.size(); i++)
    {
        if (head == Snake[i]) return true;
    }
    return false;
}
void Solution() {

    while (true)
    {
        Time++;


        //Print();

        pair<int, int> head = Snake.front();

        int nx = head.first + dx[dir];
        int ny = head.second + dy[dir];

        if (!InRange(nx, ny)) break ;

        Snake.insert(Snake.begin(), { nx, ny });
        if (isTwist()) break;

        //다음칸이 사과였다 ? 
        if (grid[nx][ny] == -1) {
            grid[nx][ny] = 0;

        }
        else {
            //사과가 아니면 꼬리를 먼저 잘라야한다 
            Snake.pop_back();
        }

        //게임 시작 시간으로부터 Time초가 끝난 뒤에 왼쪽(C가 'L') 또는 오른쪽(C가 'D')로 90도 방향을 회전시킨다는 뜻이다
        if (Time == Info.front().first) {
            if (Info.front().second == 'L') {
                dir = ((dir - 1) + 4) % 4;
            }
            else if (Info.front().second == 'D') {
                //오른쪽으로 90도 회전  시계
                dir = (dir + 1) % 4;
            }
            Info.erase(Info.begin());          
        }
    }
}
int main() {

    cin >> n >> k;
    for (int i = 0; i < k; i++)
    {
        int a = 0, b = 0; cin >> a >> b;
        grid[a][b] = -1;
    }
    Snake.push_back({ 1, 1 });

    cin >> L;

    //처음 방향은 오른쪽이다 
    dir = 1;

    for (int i = 0; i < L; i++)
    {
        int moveTime = 0;
        char trans_dir = 'a';
        cin >> moveTime >> trans_dir;
        Info.push_back({ moveTime, trans_dir });
    }

    Solution();
    cout << Time;
    return 0;
}

'알고리즘' 카테고리의 다른 글

백준 쿼드트리 (c++, recursion)  (0) 2021.12.24
백준 피보나치 수 2747  (0) 2021.12.22
네트워크 복구 백준 2211 (c++)  (0) 2021.12.16
길 찾기 게임 (c++)  (0) 2021.12.15
백준 중량제한 1939(c++)  (0) 2021.12.13