SW Expert Academy
SW 프로그래밍 역량 강화에 도움이 되는 다양한 학습 컨텐츠를 확인하세요!
swexpertacademy.com
또다시 시뮬레이션 문제!
시뮬레이션 문제의 핵심은 문제를 얼마나 빨리 이해하느냐인듯...
집중해서 안보면 문제를 이해하는데에만 5-7분은 걸리는 것 같다.
우선 나의 풀이는
#include <cstdio>
#include <utility>
#include <vector>
using namespace std;
// type으로 저장해둠, 미생물의 위치(x, y), 미생물의 수, 미생물의 방향
typedef vector<pair<pair<int, int>, pair<int, int>>> germ_vector;
typedef pair<pair<int, int>, pair<int, int>> germ_type;
// testcase 확인을 위한 입력 설정
FILE* in = fopen("input.txt", "r");
int t;
int n;
int k;
int m;
//방향 설정, 0 -> 1, 1 -> 0, 2 -> 3, 3-> 2 로 이동해서 별도의 변환 배열도 만들었다.
int dir_x[4] = { -1, 1, 0, 0 };
int dir_y[4] = { 0, 0, -1, 1 };
int trans[4] = {1, 0, 3, 2};
int solution(int n, int m, int k, germ_vector& germ) {
for (int g = 0; g < m; g++)
{
// 한 곳에서 겹치는 경우 전체 미생물을 저장할 배열, 빠르게 찾을 수 있도록 하기 위해
// 2차원 배열로 설정해 둠
int delay[101][101] = {0 ,};
// 미생물이 모두 없어지면 m 시간을 돌 필요 없음.
if (germ.empty())
break;
// 미생물 처음부터 끝까지 순회
for (int i = 0; i < germ.size(); i++)
{
int now_x = germ[i].first.first; int now_y = germ[i].first.second;
int germ_num = germ[i].second.first; int now_dir = germ[i].second.second;
//미생물 위치 이동
now_x = now_x + dir_x[now_dir];
now_y = now_y + dir_y[now_dir];
//만약 벽이라면 미생물 절반, 방향 반대로
if (now_x == 0 || now_y == 0 || now_x == n - 1 || now_y == n - 1)
{
germ_num = germ_num / 2;
now_dir = trans[now_dir];
}
// 미생물 정보 갱신
germ_type renew = make_pair(make_pair(now_x, now_y), make_pair(germ_num, now_dir));
germ[i] = renew;
// 앞선 미생물들 중에 겹치는 위치에 있는 것들을 탐색
for (int j = 0; j < i; j++)
{
int tmp_x = germ[j].first.first; int tmp_y = germ[j].first.second;
//겹칠 경우
if (now_x == tmp_x && now_y == tmp_y)
{
int tmp_num = germ[j].second.first;
int remove_idx;
int new_num = germ_num + tmp_num;
// 미생물 숫자 비교, 작은 쪽의 미생물은 데이터를 삭제
if (tmp_num > germ_num)
{
remove_idx = i;
}
else
{
remove_idx = j;
}
// 2차원 배열에 이미 값이 있는지 살피고, 있다면 원래 값에다가 현재 미생물 수 추가
if (delay[now_x][now_y] != 0)
{
delay[now_x][now_y] = delay[now_x][now_y] + germ_num;
}
//아니라면 새로 만들어줌(현재 미생물 수, 겹치는 미생물 수)
else
{
delay[now_x][now_y] = new_num;
}
// 수가 작은 미생물 데이터는 삭제
germ.erase(germ.begin() + remove_idx);
// 수가 모두 앞으로 당겨졌기 때문에 i는 증가하지 않도록 줄임
i--;
// 다음 미생물으로 바로 이동
break;
}
}
}
// 한 시간이 끝난 이후 2차원 배열의 값을 이용하여 전체 미생물 수 갱신
for (int i = 0; i < germ.size(); i++)
{
int now_x = germ[i].first.first; int now_y = germ[i].first.second;
if (delay[now_x][now_y] != 0)
germ[i].second.first = delay[now_x][now_y];
}
}
//미생물 데이터가 하나도 없다면 0
if(germ.empty())
return 0;
// 아니라면 전체 순회하며 미생물 수 합을 구해줌
else
{
int ans = 0;
for (int i = 0; i < germ.size(); i++)
ans = ans + germ[i].second.first;
return ans;
}
}
int main() {
fscanf(in, "%d", &t);
for (int i = 0; i < t; i++)
{
fscanf(in, "%d %d %d", &n, &m, &k);
germ_vector germ;
for (int j = 0; j < k; j++)
{
int a, b, c, d;
fscanf(in, "%d %d %d %d", &a, &b, &c, &d);
germ.push_back(make_pair(make_pair(a, b), make_pair(c, d - 1)));
}
printf("#%d %d\n", i + 1, solution(n, m, k, germ));
}
}
구현에 애를 먹었던 부분은
최대 4방향에서 미생물이 합쳐질 수 있는데, 이때 가장 큰 수를 가진 미생물을 선정하고 그 전체 값을 저장하는 부분이다.
나는 이를 각각의 미생물의 데이터 갱신이 끝난 뒤, 앞선 미생물들의 위치 정보를 비교하여 겹칠 때마다 미생물 수가 큰 데이터만 남기고 나머지는 삭제하고 미생물의 합은 2차원 배열에 저장하는 방식으로 구현했다. 즉, 방향 값은 벡터에 남기고 전체 미생물의 합은 2차원 배열에 따로 저장한 것이다. 처음에는 미생물의 합 또한 벡터에다 구현했는데 탐색에 시간이 많이 들어 이차원 배열에 구현했다.
'알고리즘 > SW Expert Academy' 카테고리의 다른 글
[SW Expert Academy] 2115. 벌꿀 채취 C/C++ 풀이 (0) | 2020.08.09 |
---|---|
백준 14500번 테트로미노 C/C++ 풀이 (0) | 2020.08.08 |
[SW Expert Academy] 2117. 홈 방범 서비스 C/C++ 풀이 (0) | 2020.08.07 |
[SW Expert Academy] 5648. 원자 소멸 시뮬레이션 C/C++ 풀이 (0) | 2020.08.05 |