알고리즘 문제 풀이/삼성 SW 역량 테스트
[백준] 21610번 마법사 상어와 비바라기 (C++)
다락공방
2024. 4. 7. 01:18
[문제]
https://www.acmicpc.net/problem/21610
21610번: 마법사 상어와 비바라기
마법사 상어는 파이어볼, 토네이도, 파이어스톰, 물복사버그 마법을 할 수 있다. 오늘 새로 배운 마법은 비바라기이다. 비바라기를 시전하면 하늘에 비구름을 만들 수 있다. 오늘은 비바라기
www.acmicpc.net
[풀이]
전에 풀었던 삼성기출 문제 처럼 순서대로 구현하니 그리 어렵지 않았다.
그런데 오래걸린 알고리즘이... 구름이 상, 좌 방향으로 갈 시 - 좌표가 되었을때 처리하는 방법을 고민하는데 조금 시간이 걸렸다. +가 될때까지 while문으로 +N 만큼 증가시키는 방법을 사용했다.
구름의 대각선 방향움직임은 만들어놓은 상하좌우 움직임을 합쳐서 사용. 물복사 버그에서도 BFS의 대각선 방향응용을 해서 풀었는데, 이 두가지가 흥미로웠다.
[코드]
#include <bits/stdc++.h>
using namespace std;
#define X first
#define Y second
int N, M;
int d, s;
int board[51][51];
vector <pair<int,int>> cloud;
bool vis[51][51];
void move(int dir, int step){
if(dir == 1){ //좌
for(int i = 0; i < cloud.size(); i++){
cloud[i].Y -= step;
while(cloud[i].Y < 0)
cloud[i].Y += N;
}
}
if(dir == 2){ //좌상
move(1,step);
move(3,step);
}
if(dir == 3){//상
for(int i = 0; i < cloud.size(); i++){
cloud[i].X -= step;
while(cloud[i].X < 0)
cloud[i].X += N;
}
}
if(dir == 4){ //우상
move(3,step);
move(5,step);
}
if(dir == 5){//우
for(int i = 0; i < cloud.size(); i++){
cloud[i].Y += step;
cloud[i].Y %= N;
}
}
if(dir == 6){ //우하
move(5,step);
move(7,step);
}
if(dir == 7){//하
for(int i = 0; i < cloud.size(); i++){
cloud[i].X += step;
cloud[i].X %= N;
}
}
if(dir == 8){//좌하
move(7,step);
move(1,step);
}
}
int dx[4] = {1,1,-1,-1};
int dy[4] ={1,-1,1,-1}; //우하, 좌하, 우상, 좌상
void bug (int x, int y){
for(int i = 0; i < 4; i++){
int nx = x + dx[i];
int ny = y + dy[i];
if(nx < 0 || nx >= N || ny < 0 || ny >= N) continue; //넘어간건 스킵
if(board[nx][ny] != 0) board[x][y]++;
}
}
int main() {
cin >> N >> M;
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
cin >> board[i][j];
}
}
cloud.push_back({N - 1, 0});
cloud.push_back({N - 1, 1});
cloud.push_back({N - 2, 0});
cloud.push_back({N - 2, 1}); //비바람 만들기..
for(int k = 0; k < M; k++){ //M가지 이동
for(int i = 0; i < N; i++){
memset(vis[i],false,sizeof(vis[i]));
}
cin >> d >> s;
move(d,s); //1. 비바람 이동
for(int i = 0; i < cloud.size();i++) {
board[cloud[i].X][cloud[i].Y] += 1; //2.비내리기
vis[cloud[i].X][cloud[i].Y] = 1;
}
for(int i = 0; i < cloud.size();i++) {
bug(cloud[i].X,cloud[i].Y); //3.물복사 버그
}
cloud.clear(); //구름 없어짐...
for(int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
if (board[i][j] >= 2 && !vis[i][j]) {
cloud.push_back({i, j});
board[i][j] -= 2;
}
}
}
}
int sum = 0;
for(int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
sum+= board[i][j];
}
}
cout << sum;
}
플레티넘이나 골드 상위문제는 풀기 겁나서... 낮은거부터 손대는중...