알고리즘/삼성 sw 역량테스트 기출문제

백준 마법상어와 비바라기(c++)

그린푸딩 2023. 4. 7. 00:47
728x90
반응형

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

21610번: 마법사 상어와 비바라기

마법사 상어는 파이어볼, 토네이도, 파이어스톰, 물복사버그 마법을 할 수 있다. 오늘 새로 배운 마법은 비바라기이다. 비바라기를 시전하면 하늘에 비구름을 만들 수 있다. 오늘은 비바라기

www.acmicpc.net

 
문제풀때 주의해야할점 
1. 새로운 구름 위치를 표시할때 예를들어
(4,1)->(1,1)  
(1,1)>(2,1) 
이처럼 이동할때 (4,1)을 배열에서 값을 0으로 만들고 (1,1)을 1로 바꾸는것처럼 알고리즘을 짜면 뒤에서 (1,1)->(2,1)에서 새로 갱신해서 1로 있어야할 값을 0으로 바꿔버린다. 그래서 그냥 새로운 배열을 만들고, 다시 기존 배열에 복사하는게 낫다.
 
다른 답안안보고 풀어서 뿌듯하다..

#include<iostream>
#include<vector> 
#include<cmath>
#include<deque>

using namespace std;

int A[55][55]; //바구니에 저장된 물의 양 

vector<pair<int, int>>info;

int dr[9] = {0,0,-1,-1,-1,0,1,1,1};
int dc[9] = {0,-1,-1,0,1,1,1,0,-1};

int N, M;
vector<pair<int, int>>cloud;
vector<pair<int, int>>cloud3;
vector<vector<int>>rainy_cloud;
void make_cloud() { //구름 정보 
  
    for (int i = N - 1; i <= N; i++) {
        for (int j = 1; j <= 2; j++) {
            rainy_cloud[i][j] = 1;
            cloud.push_back({ i,j }); //현재 구름 정보 
        }
    }    
}

//1.구름 이동 
void move_cloud(int d, int s) {

    int move = s % N; //움직이는 칸 갯수 
    vector<vector<int>>rainy_cloud2; 
    rainy_cloud2.assign(55, vector<int>(55, 0));
    for (int i = 0; i < cloud.size(); i++) {
        int r = cloud[i].first; 
        int c = cloud[i].second; 
       
        int nr = r + dr[d] * move;
        int nc = c + dc[d] * move;
  
        if (nr > N)nr -= N;
        if (nc > N)nc -= N;
        if (nr < 1)nr += N;
        if (nc < 1)nc += N;

        cloud3.push_back({ nr,nc }); 
      
        rainy_cloud2[nr][nc] = 1;       
    }
    rainy_cloud = rainy_cloud2;

}
//2. 물증가 +1 
void rains() {
   
    //durlqnxj answpdlTdma 
    for (int i = 0; i < cloud3.size(); i++) {
     
        A[cloud3[i].first][cloud3[i].second]= A[cloud3[i].first][cloud3[i].second]+1;
       
    }
  
}

//4. 물복사버스 마법
void new_magic() {
   
    for (int i = 0; i < cloud3.size(); i++) {
        int r = cloud3[i].first;
        int c = cloud3[i].second;
       
        int sum = 0; 
        for (int i = 2; i <= 8; i+=2) {
            int nr = r + dr[i];
            int nc = c + dc[i];
            if (nr<1 || nr>N || nc<1 || nc>N)continue;
            if (A[nr][nc])sum++; 
        }
        A[r][c] += sum;
    }    

}
//새로운 구름 생기기 
void new_cloud() {
    
    vector<pair<int, int>>cloud2;
    for (int i = 1; i <= N; i++) {
        for (int j = 1; j <= N; j++) {
            if (A[i][j] >= 2 && !rainy_cloud[i][j]) {
                cloud2.push_back({ i,j });
                 A[i][j] -= 2;
            }
        }
    }
    
;    cloud = cloud2;

    //갱신하기 
    for (int i = 1; i <= N; i++) {
        for (int j = 1; j <= N; j++) {
            rainy_cloud[i][j] = 0;
        }
    }
    for (int i = 0; i < cloud.size(); i++) {
        rainy_cloud[cloud[i].first][cloud[i].second] = 1;
    }
    vector<pair<int, int>>t;
    cloud3 = t; 
        
 }

int cnt() {
   
    int ans = 0;

    for (int i = 1; i <= N; i++) {
        for (int j = 1; j <= N; j++) {
            ans += A[i][j];
          
        }
      
    }

    return ans; 
}
int main() {

    rainy_cloud.assign(55, vector<int>(55, 0));
    for (int i = 0; i < 55; i++) {
        for (int j = 0; j < 55; j++) {
            A[i][j] = 0;
        }
   }
    cin >> N >> M;
    
    for (int i = 1; i <= N; i++) {
        for (int j = 1; j <= N; j++) {
            cin >> A[i][j];

        }
    }
   
    //구름 이동정보
    for (int i = 0; i < M; i++) {
        int d, s;
        cin >> d >> s;
        info.push_back({ d,s });
    }
   
    //비구름 만들기 
    make_cloud();
    
    //m번 구름 이동시키기 
   
    for (int i = 0; i < M; i++) {
        
        //1.구름 d방향으로 s칸 이동시키기 
        move_cloud(info[i].first, info[i].second);
       
        //2. 구름이 있는 칸에 물+1 wnd
        rains();
        
        //3.물복사버그 마법 
        new_magic();

        new_cloud();
    }
    
    //물의 양 계산
    cout<<cnt();



    return 0;
}
728x90
반응형