백준 [16235] "나무 제테크"

Kimbab1004·2024년 8월 27일
0

Algorithm

목록 보기
80/102

백준 마법사 상어와 파이어볼과 유사한 문제였다. 과거 해결했던 경험으로 골3 난이도에 비해 쉽게 문제를 풀어나갈 수 있었지만 한가지 문제점이 있었다.

Map에 심은 나무는 해당 지역 양분보다 나이가 많을 경우 죽어야 하는데, 이 죽을 경우 Map에서 죽은 나무를 치우는 방식을 생각하지 못했다. 그래서 죽은 나무의 나이를 -2로 설정하고 제출하니 죽은 나무를 모두 고려한 탓에 시간 초과가 나오게 되었다. 방법은 마법사 상어 해결 방식에 사용한 것 처럼 Map을 sort하고 해결한 나무는 vector 에 넣은 다음 map.clear를 통해 해당 맵을 지우고 죽지 않은 나무(vector)를 다시 map의 해당 구역에 넣어주는 방식 이였다.

#include <iostream>
#include <vector>
#include <cstring>
#include <algorithm>

using namespace std;

struct TREE {
	int age;
	int x;
	int y;
	bool dead = false;

	bool operator<(const TREE& other) const {
		return age < other.age;
	}
};
int n, m, k;

bool check[100][100] = { false };
//심어져 있는 나무
vector<int> map[100][100];
//겨울에 추가되는 비료
int fertilizer[100][100];
//현재 비료
int cur_fertilizer[100][100] = { 5 };
//묘목 정보
vector<TREE> tree;

int result = 0;

void input() {
	cin >> n >> m >> k;
	for (int i = 0; i < n; i++) {
		for (int j = 0; j < n; j++) {
			cin >> fertilizer[i][j];
		}
	}
	for (int i = 0; i < m; i++) {
		//위치,위치,나이
		int x, y, z;
		cin >> x >> y >> z;
		tree.push_back({ z ,x - 1, y - 1});
	}
	return;
}
//나무가 자신의 나이만큼 양분을 먹고, 나이가 1 증가한다.각각의 나무는 나무가 있는 1×1 크기의 칸에 있는 양분만 먹을 수 있다.
//하나의 칸에 여러 개의 나무가 있다면, 나이가 어린 나무부터 양분을 먹는다.
//만약, 땅에 양분이 부족해 자신의 나이만큼 양분을 먹을 수 없는 나무는 양분을 먹지 못하고 즉시 죽는다.
void spring() {
	sort(tree.begin(), tree.end());
	for (int i = 0; i < tree.size(); i++) {
		int x = tree[i].x;
		int y = tree[i].y;
		int age = tree[i].age;

		if (cur_fertilizer[x][y] - age > 0) {
			//양분이 남아있기 때문에 현재 양분을 나무가 필요한 만큼 제외시킴
			cur_fertilizer[x][y] -= age;
			//나무가 양분을 먹었기 때문에 나이가 1 증가함
			tree[i].age++;
		}
		else {
			tree[i].dead = true;
			//양분이 없으면 죽임
			continue;
		}
	}
}

void summer() {
	sort(tree.begin(), tree.end());
	memset(check, false, sizeof(check));
	//여름에는 봄에 죽은 나무가 양분으로 변하게 된다. 각각의 죽은 나무마다 나이를 2로 나눈 값이 나무가 있던 칸에 양분으로 추가된다. 소수점 아래는 버린다.

	for (int i = 0; i < tree.size(); i++) {
		int x = tree[i].x;
		int y = tree[i].y;
		//만약 죽은 나무 일시
		if (tree[i].dead == true) {
			//죽은 나무의 나이
			int age = tree[i].age;
			//현재 비료에 죽은 나무의 나이 /2값 추가
			cur_fertilizer[x][y] += age / 2;
		}
	}
}

int dx[8] = { -1,-1,-1,0,0,1,1,1 };
int dy[8] = { -1,0,1,-1,1,-1,0,1 };

//가을에는 나무가 번식한다.번식하는 나무는 나이가 5의 배수이어야 하며, 
//인접한 8개의 칸에 나이가 1인 나무가 생긴다.어떤 칸(r, c)와 인접한 칸은(r - 1, c - 1), (r - 1, c), (r - 1, c + 1), (r, c - 1), (r, c + 1), (r + 1, c - 1), (r + 1, c), (r + 1, c + 1) 
//이다.상도의 땅을 벗어나는 칸에는 나무가 생기지 않는다.
void fall() {

	for (int i = 0; i < tree.size(); i++) {
		int x = tree[i].x;
		int y = tree[i].y;
			//번식 하는 나무는 나이가 5의 배수이여야 하고 죽은 나무가 아니여야 한다.
			if (tree[i].dead == true|| tree[i].age % 5 != 0) continue;
			for (int i = 0; i < 7; i++)
			{
				int nx = x + dx[i];
				int ny = y + dy[i];
				//상도의 칸을 벗어나면 안됨
				if (0 <= nx && nx < n && 0 <= ny && ny < n) {
					tree.push_back({ 1,nx, ny,false });
				}
		}
	}
}
//겨울에는 S2D2가 땅을 돌아다니면서 땅에 양분을 추가한다. 각 칸에 추가되는 양분의 양은 A[r][c]이고, 입력으로 주어진다.
void winter() {
	for (int i = 0; i < n; i++) {
		for (int j = 0; j < n; j++) {
			cur_fertilizer[i][j] += fertilizer[i][j];
		}
	}
}

void solve() {

	for (int i = 0; i < 4; i++) {
		//봄
		spring();
		//여름
		summer();
		//가을
		fall();
		//겨울
		winter();
	}

	for (int i = 0; i < tree.size(); i++) {
		if (tree[i].age > 0 || tree[i].dead == false) {
			result++;
		}
	}

	cout << result;
}

int main() {
	ios_base::sync_with_stdio(false);
	cin.tie(NULL);
	cout.tie(NULL);

	input();
	solve();

	return 0;
}
#include <iostream>
#include <vector>
#include <cstring>
#include <algorithm>

using namespace std;

int dx[8] = { -1,-1,-1,0,0,1,1,1 };
int dy[8] = { -1,0,1,-1,1,-1,0,1 };

int n, m, k;

//심어져 있는 나무
vector<int> map[100][100];
//겨울에 추가되는 비료
int fertilizer[100][100];
//현재 비료
int cur_fertilizer[100][100];
//묘목 정보

int result = 0;

void input() {
	cin >> n >> m >> k;
	for (int i = 1; i <= n; i++) {
		for (int j = 1; j <= n; j++) {
			cin >> fertilizer[i][j];
			cur_fertilizer[i][j] = 5;
		}
	}
	for (int i = 0; i < m; i++) {
		//위치,위치,나이
		int x, y, z;
		cin >> x >> y >> z;
		map[x][y].push_back(z);
	}
	return;
}
//나무가 자신의 나이만큼 양분을 먹고, 나이가 1 증가한다.각각의 나무는 나무가 있는 1×1 크기의 칸에 있는 양분만 먹을 수 있다.
//하나의 칸에 여러 개의 나무가 있다면, 나이가 어린 나무부터 양분을 먹는다.
//만약, 땅에 양분이 부족해 자신의 나이만큼 양분을 먹을 수 없는 나무는 양분을 먹지 못하고 즉시 죽는다.
void spring() {
	for (int i = 1; i <= n; i++) {
		for (int j = 1; j <= n; j++) {
			int dead_energy = 0;
			vector<int> temp;
			if (map[i][j].size() > 0) {
				sort(map[i][j].begin(), map[i][j].end());

				for (int z = 0; z < map[i][j].size(); z++) {
					if (map[i][j][z] <= cur_fertilizer[i][j]) {
						cur_fertilizer[i][j] -= map[i][j][z];
						temp.push_back(map[i][j][z]+1);
					}
					//양분이 부족함
					else {
						dead_energy += map[i][j][z] / 2;
					}
				}
			}
			map[i][j].clear();
			for (int z = 0; z < temp.size(); z++) {
				map[i][j].push_back(temp[z]);
			}
			cur_fertilizer[i][j] += dead_energy;
		}
	}
}

//가을에는 나무가 번식한다.번식하는 나무는 나이가 5의 배수이어야 하며, 
//인접한 8개의 칸에 나이가 1인 나무가 생긴다.어떤 칸(r, c)와 인접한 칸은(r - 1, c - 1), (r - 1, c), (r - 1, c + 1), (r, c - 1), (r, c + 1), (r + 1, c - 1), (r + 1, c), (r + 1, c + 1) 
//이다.상도의 땅을 벗어나는 칸에는 나무가 생기지 않는다.
void fall() {
	for (int i = 1; i <= n; i++) {
		for (int j = 1; j <= n; j++) {
			if (map[i][j].size() > 0) {
				for (int z = 0; z < map[i][j].size(); z++) {
					if (map[i][j][z] % 5 == 0) {
						for (int e = 0; e < 8; e++) {
							int nx = i + dx[e];
							int ny = j + dy[e];
							if (0 < nx && nx <= n && 0 < ny && ny <= n) {
								map[nx][ny].push_back(1);
							}
						}
					}
				}
			}
		}
	}
}
//겨울에는 S2D2가 땅을 돌아다니면서 땅에 양분을 추가한다. 각 칸에 추가되는 양분의 양은 A[r][c]이고, 입력으로 주어진다.
void winter() {
	for (int i = 1; i <= n; i++) {
		for (int j = 1; j <= n; j++) {
			cur_fertilizer[i][j] += fertilizer[i][j];
		}
	}
}

void solve() {

	for (int i = 0; i < k; i++) {
		//봄
		spring();
		//여름
		//가을
		fall();
		//겨울
		winter();
	}


	//살아 있는 나무 구하기
	for (int i = 1; i <= n; i++) {
		for (int j = 1; j <= n; j++) {
			if (map[i][j].size() > 0) {
				result += map[i][j].size();
			}
		}
	}

	cout << result;
}

int main() {
	ios_base::sync_with_stdio(false);
	cin.tie(NULL);
	cout.tie(NULL);

	input();
	solve();

	return 0;
}

0개의 댓글