728x90
🔗 문제 링크
https://www.acmicpc.net/problem/21610
💡 문제 풀이 및 해석
시뮬레이션 문제인 만큼 문제의 조건을 그대로 구현하면 된다.
이 전에 비가 내린 것을 구분하는 것은 MAP
구조체를 만들어서 isRain
으로 판별하였고, next_x,next_y
의 99값은 문제의 조건대로 Index를 1부터 쓰기 위함이다. 정확한 방식은 아래와 같다.
- 이동하기 전에, 맵에 isRain을 모두 false로 만들어준다. (처음엔 상관없지만, 한 바퀴 돈 뒤에는 기존에 비가 내렸던 곳의 마킹을 없애주기 위함이다.)
- 방향 * 거리 만큼 이동시킨다.
- 이동시킨 거리를 N으로 나눈 나머지를 구한다. (위치 특정을 위해) 이때, -로 이동하거나 만약 N의 위치에 있다면 0 이하이므로 0 이하이면 N을 더해준다.
- 비가 내린곳은
isRain = true
으로 변경 및 문의 양을 +1 해준다. - 그 뒤에 조건에 맞게 대각선 방향에 물이 있다면, 물복사를 시켜준다.
- 기존의 Clouds를 모두 없애준 다음에 비바라기를 통해 새로운 구름들을 만든다.
⭐️ 정답 코드 및 설명
#include <iostream>
#include <vector>
using namespace std;
struct MAP {
int water = 0;
bool isRain = false;
};
int N, M;
MAP Map[51][51];
int next_x[] = {99, 0, -1, -1, -1, 0, 1, 1, 1};
int next_y[] = {99, -1, -1, 0, 1, 1, 1, 0, -1};
int water_x[] = {-1, -1, 1, 1};
int water_y[] = {-1, 1, 1, -1};
vector<pair<int, int> > dir;
vector<pair<int, int> > clouds; // x,y
void Init() {
cin >> N >> M;
for (int x = 1; x <= N; x++) {
for (int y = 1; y <= N; y++) {
cin >> Map[x][y].water;
}
}
for (int i = 0; i < M; i++) {
int d, s;
cin >> d >> s;
dir.push_back({d, s});
}
clouds.push_back({N, 1});
clouds.push_back({N, 2});
clouds.push_back({N - 1, 1});
clouds.push_back({N - 1, 2});
}
void Move(int index) {
vector<pair<int, int> > tempClouds;
int d = dir[index - 1].first, s = dir[index - 1].second;
for (pair<int, int> cloud: clouds) {
int curx = cloud.first, cury = cloud.second;
int nx = curx + next_x[d] * s, ny = cury + next_y[d] * s;
nx %= N;
ny %= N;
if (nx < 1)nx += N;
if (ny < 1)ny += N;
tempClouds.push_back({nx, ny});
Map[nx][ny].water++;
Map[nx][ny].isRain = true;
}
for (pair<int, int> cloud: tempClouds) {
int x = cloud.first, y = cloud.second;
for (int i = 0; i < 4; i++) {
int nx = x + water_x[i], ny = y + water_y[i];
if (nx > 0 && nx <= N && ny > 0 && ny <= N && Map[nx][ny].water > 0) {
Map[x][y].water++;
}
}
}
}
void Vivaragi() {
clouds.clear();
for (int x = 1; x <= N; x++) {
for (int y = 1; y <= N; y++) {
if (!Map[x][y].isRain && Map[x][y].water >= 2) {
clouds.push_back({x, y});
Map[x][y].water -= 2;
}
}
}
}
void ClearMap() {
for (int x = 1; x <= N; x++) {
for (int y = 1; y <= N; y++) {
Map[x][y].isRain = false;
}
}
}
void sol() {
int answer = 0;
Init();
for (int i = 1; i <= M; i++) {
ClearMap();
Move(i);
Vivaragi();
}
for (int x = 1; x <= N; x++) {
for (int y = 1; y <= N; y++) {
answer += Map[x][y].water;
}
}
cout << answer;
}
int main() {
sol();
return 0;
}
🤔 문제 후기
문제는 금방 풀었던 것 같다. 어제 비슷한 문제인 바법사 상어와 파이어스톰을 푼 뒤여서 더 쉽게 느껴졌던 문제였다. 중간에, next_x,y 부분에서 방향을 1
8로 해놨는데, 0
7로 설정되어 있었어서 그 부분을 빠르게 로그를 찍어보면서 알아낸 점이 컸던 것 같다.
728x90
'문제풀이 > 알고리즘 문제 풀이' 카테고리의 다른 글
[ 백준 20057 ] 마법사 상어와 토네이도 (C++) - 시뮬레이션 (0) | 2024.10.19 |
---|---|
[ 백준 20056 ] 마법사 상어와 파이어볼 (C++) - 시뮬레이션 (3) | 2024.10.12 |
[ 프로그래머스 PCCP 기출문제 2번 ] 퍼즐 게임 챌린지 (C++) - 이분 탐색 (0) | 2024.09.24 |
[ 백준 1277 ] 발전소 설치 (C++) - 그래프 이론, 구현 (0) | 2024.09.23 |
[ 백준 17142 ] 연구소 3 (C++) - BFS, 시뮬레이션 (0) | 2024.09.12 |
728x90
🔗 문제 링크
https://www.acmicpc.net/problem/21610
💡 문제 풀이 및 해석
시뮬레이션 문제인 만큼 문제의 조건을 그대로 구현하면 된다.
이 전에 비가 내린 것을 구분하는 것은 MAP
구조체를 만들어서 isRain
으로 판별하였고, next_x,next_y
의 99값은 문제의 조건대로 Index를 1부터 쓰기 위함이다. 정확한 방식은 아래와 같다.
- 이동하기 전에, 맵에 isRain을 모두 false로 만들어준다. (처음엔 상관없지만, 한 바퀴 돈 뒤에는 기존에 비가 내렸던 곳의 마킹을 없애주기 위함이다.)
- 방향 * 거리 만큼 이동시킨다.
- 이동시킨 거리를 N으로 나눈 나머지를 구한다. (위치 특정을 위해) 이때, -로 이동하거나 만약 N의 위치에 있다면 0 이하이므로 0 이하이면 N을 더해준다.
- 비가 내린곳은
isRain = true
으로 변경 및 문의 양을 +1 해준다. - 그 뒤에 조건에 맞게 대각선 방향에 물이 있다면, 물복사를 시켜준다.
- 기존의 Clouds를 모두 없애준 다음에 비바라기를 통해 새로운 구름들을 만든다.
⭐️ 정답 코드 및 설명
#include <iostream>
#include <vector>
using namespace std;
struct MAP {
int water = 0;
bool isRain = false;
};
int N, M;
MAP Map[51][51];
int next_x[] = {99, 0, -1, -1, -1, 0, 1, 1, 1};
int next_y[] = {99, -1, -1, 0, 1, 1, 1, 0, -1};
int water_x[] = {-1, -1, 1, 1};
int water_y[] = {-1, 1, 1, -1};
vector<pair<int, int> > dir;
vector<pair<int, int> > clouds; // x,y
void Init() {
cin >> N >> M;
for (int x = 1; x <= N; x++) {
for (int y = 1; y <= N; y++) {
cin >> Map[x][y].water;
}
}
for (int i = 0; i < M; i++) {
int d, s;
cin >> d >> s;
dir.push_back({d, s});
}
clouds.push_back({N, 1});
clouds.push_back({N, 2});
clouds.push_back({N - 1, 1});
clouds.push_back({N - 1, 2});
}
void Move(int index) {
vector<pair<int, int> > tempClouds;
int d = dir[index - 1].first, s = dir[index - 1].second;
for (pair<int, int> cloud: clouds) {
int curx = cloud.first, cury = cloud.second;
int nx = curx + next_x[d] * s, ny = cury + next_y[d] * s;
nx %= N;
ny %= N;
if (nx < 1)nx += N;
if (ny < 1)ny += N;
tempClouds.push_back({nx, ny});
Map[nx][ny].water++;
Map[nx][ny].isRain = true;
}
for (pair<int, int> cloud: tempClouds) {
int x = cloud.first, y = cloud.second;
for (int i = 0; i < 4; i++) {
int nx = x + water_x[i], ny = y + water_y[i];
if (nx > 0 && nx <= N && ny > 0 && ny <= N && Map[nx][ny].water > 0) {
Map[x][y].water++;
}
}
}
}
void Vivaragi() {
clouds.clear();
for (int x = 1; x <= N; x++) {
for (int y = 1; y <= N; y++) {
if (!Map[x][y].isRain && Map[x][y].water >= 2) {
clouds.push_back({x, y});
Map[x][y].water -= 2;
}
}
}
}
void ClearMap() {
for (int x = 1; x <= N; x++) {
for (int y = 1; y <= N; y++) {
Map[x][y].isRain = false;
}
}
}
void sol() {
int answer = 0;
Init();
for (int i = 1; i <= M; i++) {
ClearMap();
Move(i);
Vivaragi();
}
for (int x = 1; x <= N; x++) {
for (int y = 1; y <= N; y++) {
answer += Map[x][y].water;
}
}
cout << answer;
}
int main() {
sol();
return 0;
}
🤔 문제 후기
문제는 금방 풀었던 것 같다. 어제 비슷한 문제인 바법사 상어와 파이어스톰을 푼 뒤여서 더 쉽게 느껴졌던 문제였다. 중간에, next_x,y 부분에서 방향을 1
8로 해놨는데, 0
7로 설정되어 있었어서 그 부분을 빠르게 로그를 찍어보면서 알아낸 점이 컸던 것 같다.
728x90
'문제풀이 > 알고리즘 문제 풀이' 카테고리의 다른 글
[ 백준 20057 ] 마법사 상어와 토네이도 (C++) - 시뮬레이션 (0) | 2024.10.19 |
---|---|
[ 백준 20056 ] 마법사 상어와 파이어볼 (C++) - 시뮬레이션 (3) | 2024.10.12 |
[ 프로그래머스 PCCP 기출문제 2번 ] 퍼즐 게임 챌린지 (C++) - 이분 탐색 (0) | 2024.09.24 |
[ 백준 1277 ] 발전소 설치 (C++) - 그래프 이론, 구현 (0) | 2024.09.23 |
[ 백준 17142 ] 연구소 3 (C++) - BFS, 시뮬레이션 (0) | 2024.09.12 |