728x90
역시나 구현 문제는 매우 복잡하기 때문에, 실수가 생기면 그걸 찾는 데 시간이 더 걸린다.
따라서 처음부터 실수를 하지 않도록 주의해야 한다. 하지만 이번에도 실수를 해버렸고, 나와 비슷한 실수를 한 사람의 질문 글로 인해 찾을 수 있었다.
<토네이도의 움직임>
N = 5인 경우
- 서1, 남1, 동2, 북2, 서 3, 남3, 동4, 북4, 서4
- 동서남북 방향은 계속 바뀐다.
- 각 숫자는 두번씩 반복된다.
- 마지막 숫자만 세번 반복된다.
<확산 알고리즘>
- 하나의 함수로 처리하기 보다는, 동서남북 각 경우의 10가지 확산 방향을 배열에 저장하여 사용하였다. (여기서 실수가 나왔다.)
<주의할 점>
- 남는 모래가 '알파'로 간다고 해서, 처음부터 '알파'의 비율을 구하려고 하면 안된다. '나머지 비율'로 확산하는 모래는 소수가 아니라 정수이기 때문이다. 따라서 먼저 '나머지 비율'로 확산되는 모래의 총량을 구하고, Y 위치에서 그 총량을 뺀 값을 '알파'에 더해주어야 한다.
- 격자 밖으로 나간 모래의 양을 구해야 하므로 배열의 크기는 N보다 상하좌우로 2만큼 커야 한다. (확산될 때 Y의 위치에서 최대 2만큼 떨어진 거리로 모래가 퍼지므로) => 입력 받을 때, 시작점을 구할 때도 이 점을 유의해야 한다.
#include <stdio.h>
#include <vector>
using namespace std;
const int dy[4] = {0, 1, 0, -1}; //서 남 동 북
const int dx[4] = {-1, 0, 1, 0};
int map[503][503] = {0, };
int n;
int total = 0;
//확산 비율
const int per[9] = {1, 1, 2, 7, 7, 2, 10, 10, 5};
//x기준에서 상대 위치
const int pos_y[4][10] = {{-1, 1, -2, -1, 1, 2, -1, 1, 0, 0},
{0, 0, 1, 1, 1, 1, 2, 2, 3, 2},
{-1, 1, -2, -1, 1, 2, -1, 1, 0, -2},
{0, 0, -1, -1, -1, -1, -2, -2, -3, 0}};
const int pos_x[4][10] = {{0, 0, -1, -1, -1, -1, -2, -2, -3, -2},
{-1, 1, -2, -1, 1, 2, -1, 1, 0, 0},
{0, 0, 1, 1, 1, 1, 2, 2, 3, 0},
{-1, 1, -2, -1, 1, 2, -1, 1, 0, 2}};
int y;
int x;
void spread(int direction){
//x위치
int pre_y = y;
int pre_x = x;
//y위치
y += dy[direction];
x += dx[direction];
int tot_temp = 0;
//확산
for (int i = 0; i < 9; ++i){
int plus = map[y][x] * per[i] / 100;
map[pre_y + pos_y[direction][i]][pre_x + pos_x[direction][i]] += plus;
tot_temp += plus;
}
//알파채우기
map[y + dy[direction]][x + dx[direction]] += (map[y][x] - tot_temp);
//모두 확산 뒤 소멸
map[y][x] = 0;
}
int main(){
scanf("%d", &n);
for (int i = 2; i < 2 + n; ++i){
for (int j = 2; j < 2 + n; ++j){
scanf("%d", &map[i][j]);
}
}
int start = 0;
y = n / 2 + 2;
x = n / 2 + 2;
for (int i = 1; i <= n - 1; ++i){
for (int j = 0; j < 3; ++j){
if (i != n - 1 && j == 2){
continue;
}
for (int k = 0; k < i; ++k){
int dir = start % 4;
if (dir == 4){
dir = 0;
}
// 확산
spread(dir);
}
++start;
}
}
//격자 밖 모래 계산
for (int i = 0; i < n + 4; ++i){
for (int j = 0; j < n + 4; ++j){
if (i >= 2 && i < n + 2 && j >= 2 && j < n + 2){
continue;
}
total += map[i][j];
}
}
printf("%d", total);
}
'백준' 카테고리의 다른 글
[C++ 백준 삼성 SW 역량 기출 문제 - 15684 사다리 조작] (0) | 2022.04.24 |
---|---|
[C++ 백준 삼성 SW 역량 기출 문제 - 21609 상어 중학교] (0) | 2022.04.23 |
[C++ 백준 삼성 SW 역량 기출 문제 - 20058 마법사 상어와 파이어스톰] (0) | 2022.04.22 |
[백준 1260 DFS와BFS c++] (0) | 2022.03.17 |
[c++ 백준 삼성 sw 역량 테스트 기출 문제 - 20061 모노미노도미노2] (0) | 2022.03.04 |