static int N, M, K;
static int board[2][100][100]; //현재, 다음, 방향
static int direction[2][100][100];
static int d[5][2] = {
0, 0, //X
-1, 0, //상
1, 0, //하
0, -1, //좌
0, 1 //우
};
static int changed[] = { 0, 2, 1, 4, 3 };
static bool out_of_bound(int y, int x)
{
if (y < 1 || y >= N - 1)
return true;
if (x < 1 || x >= N - 1)
return true;
return false;
}
static int solution()
{
int y, x, n, dir, turn = 0, ret = 0;
bool visit[100][100];
int max[100][100];
queue<pair<int, int>> q;
scanf("%d %d %d", &N, &M, &K);
for (int i = 0; i < K; i++)
{
scanf("%d %d %d %d", &y, &x, &n, &dir);
board[turn][y][x] = n; //미생물 수
direction[turn][y][x] = dir; //방향
q.push({ y, x }); //좌표
}
for (int t = 0; t < M; t++)
{
int sz = q.size();
ret = 0;
memset(visit, false, sizeof(visit));
memset(max, 0, sizeof(max));
//현재 큐에 있는 개수만
for (int cnt = 0; cnt < sz; cnt++)
{
pair<int, int> cur = q.front();
q.pop();
int y = cur.first, x = cur.second;
int dir = direction[turn][y][x];
int ny = y + d[dir][0], nx = x + d[dir][1];
if (out_of_bound(ny, nx)) //약품 처리된 위치
{
board[1 - turn][ny][nx] += board[turn][y][x] / 2; //절반 줄여서 누적
direction[1 - turn][ny][nx] = changed[dir]; //방향을 바꿈
ret += board[turn][y][x] / 2; //결과 누적
}
else
{
board[1 - turn][ny][nx] += board[turn][y][x]; //그대로 누적
if (board[turn][y][x] > max[ny][nx]) //군집의 수가 더 많으면
{
max[ny][nx] = board[turn][y][x]; //최대 군집의 수 초기화
direction[1 - turn][ny][nx] = dir; //그 군집의 방향으로 초기화
}
ret += board[turn][y][x]; //결과 누적
}
board[turn][y][x] = 0; //이동했으니 현재 위치는 초기화
direction[turn][y][x] = 0;
if (!visit[ny][nx]) //큐에 없는 좌표라면
{
q.push({ ny, nx });
visit[ny][nx] = true;
}
}
turn = 1 - turn; //다음으로 이동
}
memset(board, 0, sizeof(board));
return ret;
}
처음에는 현재 위치의 군집의 이동 방향을 board에 같이 저장하는 방식으로 하였다. 그러나 이 경우 한가지 문제가 있었다.
board[2][ny][nx] = dir 또는 changed[dir] 시 다음에 확인 할 좌표에 방향이 미리 바뀔 수 있다는 것이다.
그래서 board처럼 direction도 현재, 다음 저장 을 위한 배열을 추가로 생성하여 이 문제를 해결 하였다.
그리고 동시에 확산하기 때문에 하나의 셀이 여러 군집이 모일 수 있는데,
각 군집 당 체크하면서 선형 탐색으로 충분히 해결 할 수 있다.
또 동시에 라는 말이 나오면 turn = 1 - turn 을 적어 놓고 시작하는 것이 낫겠다.
마지막으로 언급 할 점은 turn = 1 - turn의 삽입 위치이다. 문제를 풀면서 실수를 하지 않은 부분이지만,
코드가 길어지면 해당 코드의 삽입 위치를 실수 할 수 있다.
다시 한번 생각해 볼 만한 점이다.
//주의사항 및 정리
1. 메모리를 많이 사용하는 것에 부담가지지 말 것, 힙영역 256MB는 int형 배열의 길이를 최대 6400만개 까지 할당 할 수 있다. 1000 * 1000 사이즈 배열을 64개 까지 만들 수 있으니 걱정하지 말 것.
2. 문제에서 방향을 1, 2, 3, 4 형식으로 준다. 별다른 언급이 없으면 나는 주로 0, 1, 2, 3으로 처리하기 때문에 놓치지 말아야할 부분이다. 그리고 이 경우 d[5][2]로 하고 d[0] = {0, 0} 으로 한다. 물론 dir = 1 부터 시작하긴 하지만 만약의 경우를 위해서 이다.
'알고리즘 > SWEA' 카테고리의 다른 글
2112. 보호 필름 (0) | 2021.11.11 |
---|---|
2105. 디저트 카페 (0) | 2021.11.11 |
2383. 점심 식사시간 (0) | 2021.11.09 |
1949. 등산로 조성 (0) | 2021.11.09 |
2115. 벌꿀 채취 (0) | 2021.11.09 |