코테 노트/백준

백준 21611 마법사 상어와 블리자드 C++

화요밍 2021. 10. 15. 15:26
728x90
반응형

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

 

21611번: 마법사 상어와 블리자드

마법사 상어는 파이어볼, 토네이도, 파이어스톰, 물복사버그, 비바라기 마법을 할 수 있다. 오늘 새로 배운 마법은 블리자드이고, 크기가 N×N인 격자에서 연습하려고 한다. N은 항상 홀수이고, (

www.acmicpc.net

 

최종 코드

 

GitHub - hwayeon351/BEAKJOON-Algorithms: 백준 알고리즘 소스 코드 모음

백준 알고리즘 소스 코드 모음. Contribute to hwayeon351/BEAKJOON-Algorithms development by creating an account on GitHub.

github.com

//
//  main.cpp
//  BJ21611
//
//  Created by 최화연 on 2022/04/27.
//

#include <iostream>
#include <vector>
#include <deque>
using namespace std;

int N, M;
int board[50][50] = {0, };
vector<pair<int, int>> cmd;

int dr[5] = {0, -1, 1, 0, 0};
int dc[5] = {0, 0, 0, -1, 1};
int dy[4] = {0, 1, 0, -1};
int dx[4] = {-1, 0, 1, 0};
int shark_r, shark_c;

int broken_beads[4] = {0, };

void break_beads(int d, int s) {
    for (int ss=1; ss<=s; ss++) {
        int r = shark_r + ss*dr[d];
        int c = shark_c + ss*dc[d];
        if (board[r][c] == 0) continue;
        board[r][c] = 0;
    }
}

void move_beads() {
    int r = shark_r;
    int c = shark_c;
    int d = 0;
    deque<int> dq;
    
    for (int n=1; n<=N; n++) {
        int nn = n;
        if (n == N) nn = N-1;
        for (int i=0; i<2; i++) {
            for (int j=0; j<nn; j++) {
                r += dy[d];
                c += dx[d];
                if (board[r][c] > 0) {
                    dq.push_back(board[r][c]);
                    board[r][c] = 0;
                }
            }
            if (n == N) break;
            d = (d+1)%4;
        }
    }
    
    r = shark_r;
    c = shark_c;
    d = 0;
    for (int n=1; n<=N; n++) {
        int nn = n;
        if (n == N) nn = N-1;
        for (int i=0; i<2; i++) {
            for (int j=0; j<nn; j++) {
                r += dy[d];
                c += dx[d];
                if (dq.empty()) return;
                board[r][c] = dq.front();
                dq.pop_front();
            }
            if (n == N) return;
            d = (d+1)%4;
        }
    }
}

bool explode_beads() {
    int r = shark_r;
    int c = shark_c;
    int d = 0;
    bool check = false;
    deque<pair<int, int>> dq;
    
    for (int n=1; n<=N; n++) {
        int nn = n;
        if (n == N) nn = N-1;
        for (int i=0; i<2; i++) {
            for (int j=0; j<nn; j++) {
                r += dy[d];
                c += dx[d];
                if (dq.empty() || board[dq.front().first][dq.front().second] == board[r][c]) {
                    dq.push_back({r, c});
                }
                else {
                    if (dq.size() >= 4) {
                        check = true;
                        broken_beads[board[dq.front().first][dq.front().second]] += dq.size();
                        while (!dq.empty()) {
                            int rr = dq.front().first;
                            int cc = dq.front().second;
                            dq.pop_front();
                            board[rr][cc] = 0;
                        }
                    }
                    dq.clear();
                    dq.push_back({r, c});
                }
            }
            if (n == N) break;
            d = (d+1)%4;
        }
    }
    
    return check;
}

void change_beads() {
    int r = shark_r;
    int c = shark_c;
    int d = 0;
    deque<pair<int, int>> dq;
    deque<int> new_beads;
    
    for (int n=1; n<=N; n++) {
        int nn = n;
        if (n == N) nn = N-1;
        for (int i=0; i<2; i++) {
            for (int j=0; j<nn; j++) {
                r += dy[d];
                c += dx[d];
                if (dq.empty() || board[dq.front().first][dq.front().second] == board[r][c]) {
                    dq.push_back({r, c});
                }
                else {
                    new_beads.push_back(dq.size());
                    new_beads.push_back(board[dq.front().first][dq.front().second]);
                    dq.clear();
                    dq.push_back({r, c});
                }
            }
            if (n == N) break;
            d = (d+1)%4;
        }
    }
    
    r = shark_r;
    c = shark_c;
    d = 0;
    
    for (int n=1; n<=N; n++) {
        int nn = n;
        if (n == N) nn = N-1;
        for (int i=0; i<2; i++) {
            for (int j=0; j<nn; j++) {
                r += dy[d];
                c += dx[d];
                if (!new_beads.empty()) {
                    board[r][c] = new_beads.front();
                    new_beads.pop_front();
                }
                else {
                    board[r][c] = 0;
                }
            }
            if (n == N) break;
            d = (d+1)%4;
        }
    }
}

void blizard() {
    for(int i=0; i<M; i++) {
        //1. 구슬 파괴하기
        break_beads(cmd[i].first, cmd[i].second);
        
        //2. 구슬 이동하기
        move_beads();
        
        //3. 구슬 폭발하기
        bool check = explode_beads();
        
        while (check) {
            move_beads();
            check = explode_beads();
        }
        
        //4. 구슬 변화하기
        change_beads();
    }
    
}

int main(int argc, const char * argv[]) {
    cin >> N >> M;
    for (int r=1; r<=N; r++) {
        for (int c=1; c<=N; c++) {
            cin >> board[r][c];
        }
    }
    
    for (int m=0; m<M; m++) {
        int d, s;
        cin >> d >> s;
        cmd.push_back({d, s});
    }
    
    shark_r = (N+1)/2;
    shark_c = (N+1)/2;
    blizard();
    
    cout << broken_beads[1] + 2*broken_beads[2] + 3*broken_beads[3] << endl;
    
    return 0;
}

풀이 과정

풀이 시간 1시간 6분

#include <iostream>
#include <vector>
#include <deque>
using namespace std;

int N, M;
int board[50][50] = {0, };
vector<pair<int, int>> cmd;

int dr[5] = {0, -1, 1, 0, 0};
int dc[5] = {0, 0, 0, -1, 1};
int dy[4] = {0, 1, 0, -1};
int dx[4] = {-1, 0, 1, 0};
int shark_r, shark_c;

int broken_beads[4] = {0, };

void break_beads(int d, int s) {
    for (int ss=1; ss<=s; ss++) {
        int r = shark_r + ss*dr[d];
        int c = shark_c + ss*dc[d];
        if (board[r][c] == 0) continue;
        board[r][c] = 0;
    }
}

void move_beads() {
    int r = shark_r;
    int c = shark_c;
    int d = 0;
    deque<int> dq;
    
    for (int n=1; n<=N; n++) {
        int nn = n;
        if (n == N) nn = N-1;
        for (int i=0; i<2; i++) {
            for (int j=0; j<nn; j++) {
                r += dy[d];
                c += dx[d];
                if (board[r][c] > 0) {
                    dq.push_back(board[r][c]);
                    board[r][c] = 0;
                }
            }
            if (n == N) break;
            d = (d+1)%4;
        }
    }
    
    r = shark_r;
    c = shark_c;
    d = 0;
    for (int n=1; n<=N; n++) {
        int nn = n;
        if (n == N) nn = N-1;
        for (int i=0; i<2; i++) {
            for (int j=0; j<nn; j++) {
                r += dy[d];
                c += dx[d];
                if (dq.empty()) return;
                board[r][c] = dq.front();
                dq.pop_front();
            }
            if (n == N) return;
            d = (d+1)%4;
        }
    }
}

bool explode_beads() {
    int r = shark_r;
    int c = shark_c;
    int d = 0;
    bool check = false;
    deque<pair<int, int>> dq;
    
    for (int n=1; n<=N; n++) {
        int nn = n;
        if (n == N) nn = N-1;
        for (int i=0; i<2; i++) {
            for (int j=0; j<nn; j++) {
                r += dy[d];
                c += dx[d];
                if (dq.empty() || board[dq.front().first][dq.front().second] == board[r][c]) {
                    dq.push_back({r, c});
                }
                else {
                    if (dq.size() >= 4) {
                        check = true;
                        broken_beads[board[dq.front().first][dq.front().second]] += dq.size();
                        while (!dq.empty()) {
                            int rr = dq.front().first;
                            int cc = dq.front().second;
                            dq.pop_front();
                            board[rr][cc] = 0;
                        }
                    }
                    dq.clear();
                    dq.push_back({r, c});
                }
            }
            if (n == N) break;
            d = (d+1)%4;
        }
    }
    
    return check;
}

void change_beads() {
    int r = shark_r;
    int c = shark_c;
    int d = 0;
    deque<pair<int, int>> dq;
    deque<int> new_beads;
    
    for (int n=1; n<=N; n++) {
        int nn = n;
        if (n == N) nn = N-1;
        for (int i=0; i<2; i++) {
            for (int j=0; j<nn; j++) {
                r += dy[d];
                c += dx[d];
                if (dq.empty() || board[dq.front().first][dq.front().second] == board[r][c]) {
                    dq.push_back({r, c});
                }
                else {
                    new_beads.push_back(dq.size());
                    new_beads.push_back(board[dq.front().first][dq.front().second]);
                    dq.clear();
                    dq.push_back({r, c});
                }
            }
            if (n == N) break;
            d = (d+1)%4;
        }
    }
    
    r = shark_r;
    c = shark_c;
    d = 0;
    
    for (int n=1; n<=N; n++) {
        int nn = n;
        if (n == N) nn = N-1;
        for (int i=0; i<2; i++) {
            for (int j=0; j<nn; j++) {
                r += dy[d];
                c += dx[d];
                if (!new_beads.empty()) {
                    board[r][c] = new_beads.front();
                    new_beads.pop_front();
                }
                else {
                    board[r][c] = 0;
                }
            }
            if (n == N) break;
            d = (d+1)%4;
        }
    }
}

void blizard() {
    for(int i=0; i<M; i++) {
        //1. 구슬 파괴하기
        break_beads(cmd[i].first, cmd[i].second);
        
        //2. 구슬 이동하기
        move_beads();
        
        //3. 구슬 폭발하기
        bool check = explode_beads();
        
        while (check) {
            move_beads();
            check = explode_beads();
        }
        
        //4. 구슬 변화하기
        change_beads();
    }
    
}

int main(int argc, const char * argv[]) {
    cin >> N >> M;
    for (int r=1; r<=N; r++) {
        for (int c=1; c<=N; c++) {
            cin >> board[r][c];
        }
    }
    
    for (int m=0; m<M; m++) {
        int d, s;
        cin >> d >> s;
        cmd.push_back({d, s});
    }
    
    shark_r = (N+1)/2;
    shark_c = (N+1)/2;
    blizard();
    
    cout << broken_beads[1] + 2*broken_beads[2] + 3*broken_beads[3] << endl;
    
    return 0;
}

이전 풀이

풀이 시간 2시간 27분

문제에서 나와 있는 대로 순서대로 구현해 나가면 된다. 각 단계별로 모듈화해서 문제를 풀었는데, 디버그 하는 과정이 꽤나 오래걸렸다.

  1. 블리자드 마법 시전
  2. 구슬 이동
  3. 구슬 폭발이 일어나지 않을 때까지 반복
    1. 구슬 폭발
    2. 구슬 이동
  4. 구슬 변화

칸의 번호 순서대로 격자를 탐색하는 것을 구현하는 것이 핵심이라고 볼 수 있다.

이를 바탕으로 구슬을 이동시키고, 폭발을 일으키고, 구슬을 변화시킬 수 있기 때문이다.

칸을 탐색하는 과정을 살펴보면 규칙이 있다.

격자 칸 번호 탐색 규칙

N = 7인 경우이다.

잘 보면 처음 상어의 위치에서부터 시작하여 방향이 바뀌는 기준이 발생하는 칸에 도달하기까지 이동해야하는 칸 수에 규칙이 있다.

이동해야하는 칸 수 = 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 6

즉, 1~N-1까지 2번씩 반복하고, 마지막 가장 윗 행은 예외적으로 N-1칸 이동하면 된다.

방향은 좌, 하, 우, 상 순서대로 바뀐다.

 

이러한 규칙을 반영해서 칸의 번호 순서대로 탐색하는 코드는 다음과 같이 짤 수 있다.

    //격자 탐색 방향
    //0->좌, 1->하, 2->우, 3->상
    int mc[4] = {-1, 0, 1, 0};
    int mr[4] = {0, 1, 0, -1};
    int r = shark_r;
    int c = shark_c;
    int ss = 0;
    int d = 0;
    bool check = true;
    for(int s=1; s<=N; s++){
        for(int i=1; i<=2; i++){
            ss = s;
            if(ss == N) ss--;
            for(int j=1; j<=ss; j++){
            	//현재 칸 (r, c)
                r += mr[d];
                c += mc[d];
            }
            if(s == N){
                check = false;
                break;
            }
            d = (d+1)%4;
        }
        if(!check) break;
    }

 

이를 활용해서 구슬 이동과 구슬 폭발, 구슬 변화 함수를 각각 짜보면 다음과 같다.

 

(1) 구슬 폭발

//폭발할 구슬의 그룹들을 담는 벡터
vector<vector<pair<int, int>>> beads_group;
//한 그룹의 구슬들을 담는 벡터
vector<pair<int, int>> beads;

//격자 탐색 방향
//0->좌, 1->하, 2->우, 3->상
int mc[4] = {-1, 0, 1, 0};
int mr[4] = {0, 1, 0, -1};

//bomb_beads_cnt[i] = 폭발한 구슬 i의 개수
int bomb_beads_cnt[4] = {0,};

//O(N^2)
int bead_bomb(){
    beads_group.clear();
    beads.clear();
    int r = shark_r;
    int c = shark_c;
    int ss = 0;
    int d = 0;
    bool check = true;
    for(int s=1; s<=N; s++){
        for(int i=1; i<=2; i++){
            ss = s;
            if(ss == N) ss--;
            for(int j=1; j<=ss; j++){
                r += mr[d];
                c += mc[d];
                //구슬 그룹이 없는 경우, 새 구슬 그룹을 만든다
                if(beads.empty()) beads.push_back({r, c});
                //그룹의 구슬 종류와 현재 칸의 구슬 종류가 같은 경우, 그룹에 추가한다
                else if(board[beads.back().first][beads.back().second] == board[r][c]){
                    beads.push_back({r, c});
                }
                //그룹의 구슬 종류와 현재 칸의 구슬 종류가 다른 경우,
                else{
                	//이전 그룹의 구슬 개수가 4개 이상인 경우, 폭발이 일어나야하므로 beads_group에 해당 그룹을 추가한다
                    if(beads.size() >= 4) beads_group.push_back(beads);
                    //새 구슬 그룹을 만든다
                    beads.clear();
                    beads.push_back({r, c});
                }
            }
            if(s == N){
                check = false;
                break;
            }
            d = (d+1)%4;
        }
        if(!check) break;
    }
    
    //폭발해서 사라진 구슬 수
    int cnt = 0;
    for(int i=0; i<beads_group.size(); i++){
    	//폭발한 구슬의 개수 카운팅
        bomb_beads_cnt[board[beads_group[i].back().first][beads_group[i].back().second]] += beads_group[i].size();
        cnt += beads_group[i].size();
        
        //폭발한 구슬을 없앤다
        for(int j=0; j<beads_group[i].size(); j++){
            board[beads_group[i][j].first][beads_group[i][j].second] = 0;
        }
    }
    return cnt;
}

 

(2) 구슬 이동

//격자 탐색 방향
//0->좌, 1->하, 2->우, 3->상
int mc[4] = {-1, 0, 1, 0};
int mr[4] = {0, 1, 0, -1};

//O(N^2)
void move_beads(){
	//현재 칸 위치
    int r = shark_r;
    int c = shark_c;
    //이전 칸 위치
    int br = shark_r;
    int bc = shark_c;
    int ss = 0;
    int d = 0;
    for(int s=1; s<=N; s++){
        for(int i=1; i<=2; i++){
            ss = s;
            if(ss == N) ss--;
            for(int j=1; j<=ss; j++){
                r += mr[d];
                c += mc[d];
                //이전 칸에 구슬이 없는 경우
                if(board[br][bc] == 0){
                	//이전 칸에 현재 칸의 구슬을 담고, 현재 칸은 비운다
                    board[br][bc] = board[r][c];
                    board[r][c] = 0;
                }
                br = r;
                bc = c;
            }
            if(s == N) return;
            d = (d+1)%4;
        }
    }
}

 

(3) 구슬 변화

//구슬의 그룹들을 담는 벡터
vector<vector<pair<int, int>>> beads_group;

//한 그룹의 구슬들을 담는 벡터
vector<pair<int, int>> beads;

//새로운 구슬을 담는 벡터
//new_beads[i] = i+1번째 구슬의 종류
vector<int> new_beads;

//격자 탐색 방향
//0->좌, 1->하, 2->우, 3->상
int mc[4] = {-1, 0, 1, 0};
int mr[4] = {0, 1, 0, -1};

//O(N^2)
void change_beads(){
    beads_group.clear();
    beads.clear();
    int r = shark_r;
    int c = shark_c;
    int ss = 0;
    int d = 0;
    bool check = true;
    for(int s=1; s<=N; s++){
        for(int i=1; i<=2; i++){
            ss = s;
            if(ss == N) ss--;
            for(int j=1; j<=ss; j++){
                r += mr[d];
                c += mc[d];
                //구슬 그룹이 없는 경우, 새 그룹을 만든다
                if(beads.empty()) beads.push_back({r, c});
                //그룹의 구슬 종류와 현재 구슬 종류가 같은 경우, 현재 구슬을 그룹에 추가한다
                else if(board[beads.back().first][beads.back().second] == board[r][c]){
                    beads.push_back({r, c});
                }
                //그룹의 구슬 종류와 현재 구슬 종류가 다른 경우,
                else{
                	//이전 구슬 그룹을 beads_group에 추가하고 새 그룹을 만든다
                    beads_group.push_back(beads);
                    beads.clear();
                    beads.push_back({r, c});
                }
            }
            if(s == N){
                check = false;
                break;
            }
            d = (d+1)%4;
        }
        if(!check) break;
    }
    
    //구슬 변화
    int A = 0;
    int B = 0;
    new_beads.clear();
    //각각의 구슬 그룹에 대한 A, B를 만들고 new_beads에 순서대로 추가한다
    for(int i=0; i<beads_group.size(); i++){
        A = beads_group[i].size();
        B = board[beads_group[i].back().first][beads_group[i].back().second];
        new_beads.push_back(A);
        new_beads.push_back(B);
    }
    
    //새로운 구슬을 격자에 적용
    r = shark_r;
    c = shark_c;
    ss = 0;
    d = 0;
    //new_beads 벡터 인덱스
    int k = 0;
    check = true;
    for(int s=1; s<=N; s++){
        for(int i=1; i<=2; i++){
            ss = s;
            if(ss == N) ss--;
            for(int j=1; j<=ss; j++){
                r += mr[d];
                c += mc[d];
                //새로운 구슬들을 모두 격자에 반영했다면, 이후 칸에는 모두 0을 넣는다
                if(k >= new_beads.size()) board[r][c] = 0;
                //k번째 새로운 구슬을 격자에 넣는다
                else board[r][c] = new_beads[k];
                k++;
            }
            if(s == N){
                check = false;
                break;
            }
            d = (d+1)%4;
        }
        if(!check) break;
    }
}

#include <iostream>
#include <vector>
using namespace std;

int N, M;

//블리자드 마법 방향
//1->상, 2->하, 3->좌, 4->우
int dr[5] = {0, -1, 1, 0, 0};
int dc[5] = {0, 0, 0, -1, 1};

//격자 탐색 방향
//0->좌, 1->하, 2->우, 3->상
int mc[4] = {-1, 0, 1, 0};
int mr[4] = {0, 1, 0, -1};
int board[50][50] = {0, };

//blizards[i] = {d, s}
vector<pair<int, int>> blizards;
//구슬의 그룹들을 담는 벡터
vector<vector<pair<int, int>>> beads_group;
//한 그룹의 구슬들을 담는 벡터
vector<pair<int, int>> beads;
vector<int> new_beads;
int shark_r = 0;
int shark_c = 0;

//bomb_beads_cnt[i] = 폭발한 구슬 i의 개수
int bomb_beads_cnt[4] = {0,};

void move_beads(){
    //현재 칸 위치
    int r = shark_r;
    int c = shark_c;
    //이전 칸 위치
    int br = shark_r;
    int bc = shark_c;
    int ss = 0;
    int d = 0;
    for(int s=1; s<=N; s++){
        for(int i=1; i<=2; i++){
            ss = s;
            if(ss == N) ss--;
            for(int j=1; j<=ss; j++){
                r += mr[d];
                c += mc[d];
                //이전 칸에 구슬이 없는 경우
                if(board[br][bc] == 0){
                    //이전 칸에 현재 칸의 구슬을 담고, 현재 칸은 비운다
                    board[br][bc] = board[r][c];
                    board[r][c] = 0;
                }
                br = r;
                bc = c;
            }
            if(s == N) return;
            d = (d+1)%4;
        }
    }
}

int bead_bomb(){
    beads_group.clear();
    beads.clear();
    int r = shark_r;
    int c = shark_c;
    int ss = 0;
    int d = 0;
    bool check = true;
    for(int s=1; s<=N; s++){
        for(int i=1; i<=2; i++){
            ss = s;
            if(ss == N) ss--;
            for(int j=1; j<=ss; j++){
                r += mr[d];
                c += mc[d];
                //구슬 그룹이 없는 경우, 새 구슬 그룹을 만든다
                if(beads.empty()) beads.push_back({r, c});
                //그룹의 구슬 종류와 현재 칸의 구슬 종류가 같은 경우, 그룹에 추가한다
                else if(board[beads.back().first][beads.back().second] == board[r][c]){
                    beads.push_back({r, c});
                }
                //그룹의 구슬 종류와 현재 칸의 구슬 종류가 다른 경우,
                else{
                    //이전 그룹의 구슬 개수가 4개 이상인 경우, 폭발이 일어나야하므로 beads_group에 해당 그룹을 추가한다
                    if(beads.size() >= 4) beads_group.push_back(beads);
                    //새 구슬 그룹을 만든다
                    beads.clear();
                    beads.push_back({r, c});
                }
            }
            if(s == N){
                check = false;
                break;
            }
            d = (d+1)%4;
        }
        if(!check) break;
    }
    
    //폭발해서 사라진 구슬 수
    int cnt = 0;
    for(int i=0; i<beads_group.size(); i++){
        //폭발한 구슬의 개수 카운팅
        bomb_beads_cnt[board[beads_group[i].back().first][beads_group[i].back().second]] += beads_group[i].size();
        cnt += beads_group[i].size();
        
        //폭발한 구슬을 없앤다
        for(int j=0; j<beads_group[i].size(); j++){
            board[beads_group[i][j].first][beads_group[i][j].second] = 0;
        }
    }
    return cnt;
}

void change_beads(){
    beads_group.clear();
    beads.clear();
    int r = shark_r;
    int c = shark_c;
    int ss = 0;
    int d = 0;
    bool check = true;
    for(int s=1; s<=N; s++){
        for(int i=1; i<=2; i++){
            ss = s;
            if(ss == N) ss--;
            for(int j=1; j<=ss; j++){
                r += mr[d];
                c += mc[d];
                //구슬 그룹이 없는 경우, 새 그룹을 만든다
                if(beads.empty()) beads.push_back({r, c});
                //그룹의 구슬 종류와 현재 구슬 종류가 같은 경우, 현재 구슬을 그룹에 추가한다
                else if(board[beads.back().first][beads.back().second] == board[r][c]){
                    beads.push_back({r, c});
                }
                //그룹의 구슬 종류와 현재 구슬 종류가 다른 경우,
                else{
                    //이전 구슬 그룹을 beads_group에 추가하고 새 그룹을 만든다
                    beads_group.push_back(beads);
                    beads.clear();
                    beads.push_back({r, c});
                }
            }
            if(s == N){
                check = false;
                break;
            }
            d = (d+1)%4;
        }
        if(!check) break;
    }
    
    //구슬 변화
    int A = 0;
    int B = 0;
    new_beads.clear();
    //각각의 구슬 그룹에 대한 A, B를 만들고 new_beads에 순서대로 추가한다
    for(int i=0; i<beads_group.size(); i++){
        A = beads_group[i].size();
        B = board[beads_group[i].back().first][beads_group[i].back().second];
        new_beads.push_back(A);
        new_beads.push_back(B);
    }
    
    //새로운 구슬을 격자에 적용
    r = shark_r;
    c = shark_c;
    ss = 0;
    d = 0;
    //new_beads 벡터 인덱스
    int k = 0;
    check = true;
    for(int s=1; s<=N; s++){
        for(int i=1; i<=2; i++){
            ss = s;
            if(ss == N) ss--;
            for(int j=1; j<=ss; j++){
                r += mr[d];
                c += mc[d];
                //새로운 구슬들을 모두 격자에 반영했다면, 이후 칸에는 모두 0을 넣는다
                if(k >= new_beads.size()) board[r][c] = 0;
                //k번째 새로운 구슬을 격자에 넣는다
                else board[r][c] = new_beads[k];
                k++;
            }
            if(s == N){
                check = false;
                break;
            }
            d = (d+1)%4;
        }
        if(!check) break;
    }
}

void play_blizards(){
    for(int i=0; i<M; i++){
        //1. 블리자드 시전 -> O(1)
        for(int s=blizards[i].second; s>=1; s--){
            int br = shark_r + dr[blizards[i].first]*s;
            int bc = shark_c + dc[blizards[i].first]*s;
            board[br][bc] = 0;
        }
        //2. 구슬 이동 -> O(N^2)
        for(int j=0; j<=blizards[i].second; j++) move_beads();
        //3. 구슬 폭발 -> O(N^2)
        int cnt = bead_bomb();
        //4. 구슬 이동 -> O(N^4)
        while(cnt > 0){
            for(int j=1; j<=cnt; j++) move_beads();
            cnt = bead_bomb();
        }
        //5. 구슬 변화 -> O(N^2)
        change_beads();
    }
}

int main(int argc, const char * argv[]) {
    cin >> N >> M;
    for(int r=1; r<=N; r++){
        for(int c=1; c<=N; c++){
            cin >> board[r][c];
        }
    }
    for(int i=0; i<M; i++){
        int d, s;
        cin >> d >> s;
        blizards.push_back({d, s});
    }
    shark_r = (N+1)/2;
    shark_c = (N+1)/2;
    board[shark_r][shark_c] = -1;
    play_blizards();
    cout << 1*bomb_beads_cnt[1] + 2*bomb_beads_cnt[2] + 3* bomb_beads_cnt[3] << endl;
    return 0;
}
//시간복잡도 = O(M*N^4), 공간복잡도 = O(N^2)
728x90
반응형