문제 : https://www.acmicpc.net/problem/21610
21610번: 마법사 상어와 비바라기
마법사 상어는 파이어볼, 토네이도, 파이어스톰, 물복사버그 마법을 할 수 있다. 오늘 새로 배운 마법은 비바라기이다. 비바라기를 시전하면 하늘에 비구름을 만들 수 있다. 오늘은 비바라기
www.acmicpc.net
[ 시뮬레이션 ]
이 문제는 BFS나 DFS도 필요없는 찐찐찐 시뮬레이션 문제다. (지금까지 푼 것 중에 가장 쉬움..)
위의 과정 그대로 짜면 정말 끝이다.
1) 구름 이동 : 1번째 행-N번째 행, 1번째 열-N번째 열이 연결 되어 있는 부분만 조심 하면 된다.
if (ny < 1)
ny += N;
if (nx < 1)
nx += N;
if (ny > N)
ny -= N;
if (nx > N)
nx -= N;
나는 이런 식으로 if문을 통해서 간단히 연결 해줬다.
또, 이동하는 크기 s 가 N보다 큰 경우 연결이 제대로 되지 않고 어차피 규칙적으로 움직이기 때문에
아래 처럼 s를 N보다 작은 수로 만들어줬다.
while (1)
{
if (s <= N)
break;
if (s > N)
s -= N;
}
3) 구름이 사라지는것은 함수는 만들었지만 따로 사용하지 않았다.
-> 4번과 5번 과정에서 원래 구름이 있던 좌표가 계속해서 필요했기 때문.
이 점들만 주의하면 바로 풀 수 있는 간단한 문제다 1시간 20분만에 성공😉💕
#include <iostream>
#include <vector>
using namespace std;
int N, M;
const int MAX = 51;
int bucket_map[MAX][MAX] = {0, }; //바구니에 저장된 물 양
int cloud_map[MAX][MAX] = { 0, }; //구름 위치
vector<pair<int, int>> cmd; //구름 이동 정보
//구름 이동 방향 : 좌, 좌상, 상, 상우, 우, 우하, 하, 하좌
const int dy[9] = {0,0,-1,-1,-1,0,1,1,1};
const int dx[9] = {0,-1,-1,0,1,1,1,0,-1};
//물복사버그 마법 시전 방향 : 대각선
const int diagonal_dy[4] = {-1,-1,1,1};
const int diagonal_dx[4] = {-1,1,-1,1};
void print(int map[MAX][MAX])
{
for (int y = 1; y <= N; y++)
{
for (int x = 1; x <= N; x++)
{
cout << map[y][x] << " ";
}
cout << endl;
}
cout << endl;
}
void move_cloud(int d, int s)
{
int temp[MAX][MAX] = { 0, };
while (1)
{
if (s <= N)
break;
if (s > N)
s -= N;
}
for (int y = 1; y <= N; y++)
{
for (int x = 1; x <= N; x++)
{
if (cloud_map[y][x])
{
int ny = y + s * dy[d];
int nx = x + s * dx[d];
if (ny < 1)
ny += N;
if (nx < 1)
nx += N;
if (ny > N)
ny -= N;
if (nx > N)
nx -= N;
temp[ny][nx] = 1;
}
}
}
for (int y = 1; y <= N; y++)
{
for (int x = 1; x <= N; x++)
{
cloud_map[y][x] = temp[y][x];
}
}
}
void rain()
{
for (int y = 1; y <= N; y++)
{
for (int x = 1; x <= N; x++)
{
if (cloud_map[y][x])
bucket_map[y][x]++;
}
}
}
void disappear_cloud()
{
for (int y = 1; y <= N; y++)
{
for (int x = 1; x <= N; x++)
{
cloud_map[y][x] = 0;
}
}
}
void copy_water()
{
int temp[MAX][MAX] = { 0, };
for (int y = 1; y <= N; y++)
{
for (int x = 1; x <= N; x++)
{
if (cloud_map[y][x])
{
int cnt = 0;
for (int dir = 0; dir < 4; dir++)
{
int ny = y + diagonal_dy[dir];
int nx = x + diagonal_dx[dir];
if (ny > N || nx > N || ny < 1 || nx < 1) continue;
if (bucket_map[ny][nx])
cnt++;
}
temp[y][x] += cnt;
}
}
}
for (int y = 1; y <= N; y++)
{
for (int x = 1; x <= N; x++)
{
bucket_map[y][x] += temp[y][x];
}
}
}
void appear_cloud()
{
int temp[MAX][MAX] = { 0, };
for (int y = 1; y <= N; y++)
{
for (int x = 1; x <= N; x++)
{
if (bucket_map[y][x] >= 2 && !cloud_map[y][x])
{
temp[y][x] = 1;
bucket_map[y][x] -= 2;
}
}
}
for (int y = 1; y <= N; y++)
{
for (int x = 1; x <= N; x++)
{
cloud_map[y][x] = temp[y][x];
}
}
}
int main()
{
ios_base::sync_with_stdio(false);
cout.tie(NULL);
cin.tie(NULL);
cin >> N >> M;
for (int y = 1; y <= N; y++)
{
for (int x = 1; x <= N; x++)
{
cin >> bucket_map[y][x];
}
}
for (int i = 0; i < M; i++)
{
int d, s;
cin >> d >> s;
cmd.push_back(make_pair(d, s));
}
cloud_map[N][1] = cloud_map[N][2] = cloud_map[N - 1][1] = cloud_map[N - 1][2] = 1;
for (int i = 0; i < M; i++)
{
int d = cmd[i].first;
int s = cmd[i].second;
move_cloud(d, s);
rain();
copy_water();
appear_cloud();
}
int cnt = 0;
for (int y = 1; y <= N; y++)
{
for (int x = 1; x <= N; x++)
{
cnt += bucket_map[y][x];
}
}
cout << cnt << "\n";
return 0;
}
'알고리즘 > 삼성 기출' 카테고리의 다른 글
[백준/C++] 23288번 주사위 굴리기2 - 삼성SW기출 (0) | 2022.04.06 |
---|---|
[백준/C++] 23289번 온풍기 안녕! -삼성SW기출 (0) | 2022.04.04 |
[백준/C++] 23290번 마법사 상어와 복제 - 삼성SW기출 (0) | 2022.03.30 |
[백준/C++] 14502번 연구소 - 삼성 SW 기출 (0) | 2022.02.28 |
[백준/C++] 13460번 구슬 탈출2 - 삼성SW기출 (0) | 2022.02.03 |