어흥

[백준 21610] 마법사 상어와 비바라기 (C++) 본문

알고리즘/백준

[백준 21610] 마법사 상어와 비바라기 (C++)

라이언납시오 2021. 10. 20. 22:25
728x90
반응형

문제 링크: https://www.acmicpc.net/problem/21610

 

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

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

www.acmicpc.net

1. 주의할 점

- 순서대로 정확히 구현을 한다

- 각 단계가 끝나고 초기화해야 할 부분들을 살핀다

 

2. 구현

- 배열의 범위와 방향을 1씩 줄인다

- Arr[][] 배열에 바구니의 상태를 담는다

- 최초에는 구름이 정해진곳에서 생성되므로 4구역을 Cloud 벡터에 담고 시작한다

- 각 단계가 시작하기 전에 init()을 통해 구름이 사라진곳을 나타내는 Check[][] 배열을 초기화한다

- moveCloud()를 통해 구름을 움직이며, 이때 속도가 높아서 배열의 범위의 N(N>1)배만큼 벗어날 수 있으므로, if문이 아닌 while문을 통해 y,x값을 조정한다

- rain() 함수를 통해 현재 구름이 있는곳에 비를 1 증가시키고 Check[][] 배열의 값을 true로 바꾼다

- addRain()을 통해 물복사를 수행한다

- makeCloud() 함수를 통해 Arr[][] 배열의 값이 2 이상이며 Check[][] 값이 False인 곳에서 구름을 생성한다

- 마지막으로 addTotRain() 함수를 통해 최종 상태의 Arr[][] 배열에서 바구니에 담긴 물의 합을 구한다

 

#include <iostream>
#include <queue>
#include <vector>
using namespace std;
struct info{
    int y,x;
};
int dx[8]={-1,-1,0,1,1,1,0,-1};
int dy[8]={0,-1,-1,-1,0,1,1,1};
int arr[50][50];
bool check[50][50];
int num,m,d,s;
vector<info> cloud;

void moveCloud(){
    for(int i=0;i<cloud.size();i++){
        int cx = cloud[i].x;
        int cy = cloud[i].y;
        int nx = cx + dx[d]*s;
        int ny = cy + dy[d]*s;
        while(nx<0){
            nx+=num;
        }
        while(nx>=num){
            nx-=num;
        }
        while(ny<0){
            ny+=num;
        }
        while(ny>=num){
            ny-=num;
        }
        cloud[i].x=nx;
        cloud[i].y=ny;
    }
}

void rain(){
    for(int i=0;i<cloud.size();i++){
        int cx = cloud[i].x;
        int cy = cloud[i].y;
        arr[cy][cx]++;
        check[cy][cx]=true;
    }
}

void addRain(){
    for(int i=0;i<cloud.size();i++){
        int cx = cloud[i].x;
        int cy = cloud[i].y;
        int cnt=0;
        for(int k=1;k<8;k+=2){
            int nx = cx+dx[k];
            int ny = cy+dy[k];
            if(nx>=0 && ny>=0 && nx<num && ny<num && arr[ny][nx]>0)
                cnt++;
        }
        arr[cy][cx]+=cnt;
    }
}

void init(){
    for(int i=0;i<num;i++)
        for(int j=0;j<num;j++)
            check[i][j]=false;
}

void makeCloud(){
    cloud.clear();
    for(int i=0;i<num;i++)
        for(int j=0;j<num;j++){
            if(arr[i][j]>1 && !check[i][j]){
                cloud.push_back({i,j});
                arr[i][j]-=2;
            }
        }
}

int addTotRain(){
    int result = 0;
    for(int i=0;i<num;i++)
        for(int j=0;j<num;j++)
            result+=arr[i][j];
    return result;
}

int main() {
    ios_base::sync_with_stdio(false); cin.tie(NULL); cout.tie(NULL);
    cin >> num >> m;
    for(int i=0;i<num;i++)
        for(int j=0;j<num;j++)
            cin>>arr[i][j];
            
    cloud.push_back({num-1,0});
    cloud.push_back({num-1,1});
    cloud.push_back({num-2,0});
    cloud.push_back({num-2,1});
    
    for(int i=0;i<m;i++){
        cin>>d>>s;
        d-=1;
        //초기화
        init();
        //구름 이동
        moveCloud();
        //비 내린다
        rain();
        //물 복사
        addRain();
        //구름 생성
        makeCloud();
    }
    cout << addTotRain();
    return 0;
}
728x90
반응형
Comments