[BOJ-Code] 21610 - 마법사 상어와 비바라기

Posted by DHniyeo Blog on April 8, 2024

문제 링크

💡 구현/시뮬레이션

Memory 2040KB Time 4ms Code Length 3740B

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
//입력: N 맵크기, M 이동정보 갯수.맵정보, 이동정보(d, s)
//
//	구름생성 M번 이동 명령.←, ↖, ↑, ↗, →, ↘, ↓, ↙
//	1. 구름 이동 d 방향으로 s칸이동(경계 넘어가도됨)
//	2. 구름칸 물의양 증가
//	3. 구름 사라짐
//	4. 물이증가한 칸 대각선 4개 조사하여 바구니의 물의 양이 증가함.(경계가는 칸은 제외)
//	5. 바구니ㅔ 저장된 물의 양이 2 이상인 모든칸에 구름이 생기고 물의 양이 2 줄어듬.이전에 구름이 생겼던 칸은 제외됨.
//
//	M번의 이동이 끝난후 바구니에 들어있는 물의 양의 합을 구하자.

#include<iostream>
#include<cstring>
using namespace std;

int N, M;
int water_MAP[50][50];
int cloud_MAP[50][50];
int dy[] = {0,-1,-1,-1,0,1,1,1}; // ←, ↖, ↑, ↗, →, ↘, ↓, ↙
int dx[] = { -1,-1,0,1,1,1,0,-1 };
struct info {
	int d, s;
};
info todo[100];

void init() {
	memset(water_MAP, 0, sizeof(water_MAP));
	memset(cloud_MAP, 0, sizeof(cloud_MAP));
	cin >> N >> M;
	for (int i = 0; i < N; i++) {
		for (int j = 0; j < N; j++) {
			cin >> water_MAP[i][j];
		}
	}
	for (int i = 0; i < M; i++) {
		info tmp;
		cin >> tmp.d >> tmp.s;
		tmp.d--;
		todo[i] = tmp;
	}
	// 구름 초기생성 위치
	cloud_MAP[N - 1][0] = 1;
	cloud_MAP[N - 1][1] = 1;
	cloud_MAP[N - 2][0] = 1;
	cloud_MAP[N - 2][1] = 1;
		
}
void move_cloud(int d, int s){
	int tmp_map[50][50];
	int speed = s % N;
	memset(tmp_map, 0, sizeof(tmp_map));
	for (int i = 0; i < N; i++) {
		for (int j = 0; j < N; j++) {
			// 경계를 넘어가도됨.
			if (cloud_MAP[i][j] == 0) continue;
			int ny = (i + dy[d] * speed + N) % N;
			int nx = (j + dx[d] * speed + N) % N;
			tmp_map[ny][nx] = 1;
		}
	}
	memcpy(cloud_MAP, tmp_map, sizeof(cloud_MAP));
}
void water_bam() {

	// 구름칸 물의 양 증가
	for (int i = 0; i < N; i++) {
		for (int j = 0; j < N; j++) {
			if (cloud_MAP[i][j] == 1) {
				water_MAP[i][j] += 1;
			}
		}
	}
	// 물이 증가한 칸 대각선 4개 조사해서 물의 양 증가.(경계칸 제외) - 이전 맵 조사해서 비교하기 때문에 새로운 맵을 생성해야됨.
	int tmp_map[50][50];
	memset(tmp_map, 0, sizeof(tmp_map));
	for (int i = 0; i < N; i++) {
		for (int j = 0; j < N; j++) {
			if (cloud_MAP[i][j] == 0) continue;
			int cnt = 0;
			for (int k = 1; k < 8; k = k + 2) {
				int ny = i + dy[k];
				int nx = j + dx[k];
				if (ny >= N || nx >= N || ny < 0 || nx < 0) continue;
				if (water_MAP[ny][nx] > 0) cnt++;
			}
			tmp_map[i][j] += cnt;
		}
	}
	for (int i = 0; i < N; i++) {
		for (int j = 0; j < N; j++) {
			water_MAP[i][j] += tmp_map[i][j];
		}
	}
}
void cloud_make() {
	int tmp_map[50][50]; // 구름이 생성 될 맵
	memset(tmp_map, 0, sizeof(tmp_map));
	for (int i = 0; i < N; i++) {
		for (int j = 0; j < N; j++) {
			if (cloud_MAP[i][j] == 1) continue;
			if (water_MAP[i][j] >= 2) {
				water_MAP[i][j] -= 2;
				tmp_map[i][j] = 1;
			}
		}
	}
	memcpy(cloud_MAP, tmp_map, sizeof(cloud_MAP));
}
int water_check() {
	int sum = 0;
	for (int i = 0; i < N; i++) {
		for (int j = 0; j < N; j++) {
			sum += water_MAP[i][j];
		}
	}
	return sum;
}
int main() {
	init();
	for (int i = 0; i < M; i++) {
		//	1. 구름 이동 d 방향으로 s칸이동(경계 넘어가도됨)
		move_cloud(todo[i].d, todo[i].s);
		//	2. 구름칸 물의양 증가
		//	3. 구름 사라짐
		//	4. 물이증가한 칸 대각선 4개 조사하여 바구니의 물의 양이 증가함.(경계가는 칸은 제외)
		water_bam();
		//	5. 바구니에 저장된 물의 양이 2 이상인 모든칸에 구름이 생기고 물의 양이 2 줄어듬.이전에 구름이 생겼던 칸은 제외됨.
		cloud_make();
	}
	int result = water_check();
	cout << result << endl;
}

이 코드는 N x N 크기의 바구니와 구름이 움직이는 과정을 시뮬레이션하는 프로그램이다.

초기화 단계에서는 바구니와 구름의 상태를 초기화하고, 이동 정보를 입력받는다.

move_cloud 함수는 구름을 주어진 방향과 거리만큼 이동시킨다.

water_bam 함수는 구름이 있는 칸의 물의 양을 증가시키고, 대각선 방향으로 물의 양을 증가시킨다.

cloud_make 함수는 바구니에 저장된 물의 양이 2 이상인 칸에 구름을 생성하고 물의 양을 감소시킨다.

main 함수에서는 주어진 이동 정보에 따라 구름을 이동시키고 물의 양을 조절한 뒤, 마지막에 바구니에 들어있는 물의 양의 총합을 출력한다.