진짜 오랜만에 다시 삼성 기출을 풀어본다
오랜만에 푸니 너무 오래걸린다
총 4시간은 걸린 듯
//20057번 마법사 상어와 토네이도
#include <iostream>
using namespace std;
int N;
int y;
int x;
int dy[4] = { 0, 1, 0, -1 }; //서 남 동 북
int dx[4] = { -1, 0, 1, 0 };
//비율 열개 {1,1,7,7,10,10,2,2,5,a}
int rdy[4][10] = {
{-1,1,-1,1,-1,1,-2,2,0,0},
{-1,-1,0,0,1,1,0,0,2,1},
{-1,1,-1,1,-1,1,-2,2,0,0},
{1,1,0,0,-1,-1,0,0,-2,-1}
};
int rdx[4][10] = {
{1,1,0,0,-1,-1,0,0,-2,-1},
{-1,1,-1,1,-1,1,-2,2,0,0},
{-1,-1,0,0,1,1,0,0,2,1},
{-1,1,-1,1,-1,1,-2,2,0,0}
};
double spreadRate[9] = { 0.01,0.01,0.07,0.07,0.1,0.1,0.02,0.02,0.05 };
int map[503][503];
int totalOutSand = 0;
void Init() {
for (int i = 0; i <= 500; i++) {
for (int j = 0; j <= 500; j++) {
map[i][j] = 0;
}
}
}
void BeforePrint() {
cout << "Before Move Sand\n";
for (int i = 1; i <= N; i++) {
for (int j = 1; j <= N; j++) {
cout << map[i][j] << ' ';
}
cout << "\n";
}
}
void SandPrint(int y, int x) {
cout << " Print Moved Sand\n";
for (int i = 1; i <= N; i++) {
cout << " ";
for (int j = 1; j <= N; j++) {
if (i == y && j == x) {
cout << map[i][j] << "^ ";
}
else {
cout << map[i][j] << " ";
}
}
cout << "\n";
}
}
//dir 방향으로 이동할 (y,x)의 모래를 규칙에 맞게 뿌린다
//map[][]에 뿌린 후 모래량 표시
void SpreadSand(int y, int x, int dir) {
int totalMovedSand = 0;
for (int i = 0; i < 10; i++) { //열번쨰는 a이니 확인 필요!!
int movedSand;
//바람에 의해 이동할 곳의 모래량
if (i == 9) { //a인 부분
movedSand = map[y][x] - totalMovedSand;
//cout << map[y][x] << "모래에서 전체 비율모래량 "<<totalMovedSand<<"뺀 모래량 " << movedSand << "\n";
}
else { //나머지 비율부분
movedSand = map[y][x] * spreadRate[i];
//cout << map[y][x] << "모래의 " << spreadRate[i] << "비율의 모래 " << movedSand << "\n";
}
totalMovedSand = totalMovedSand + movedSand;
int ny = y + rdy[dir][i];
int nx = x + rdx[dir][i];
//1,1 부터 N,N 격자 경계 벗어나면 모래 량 더해가기
if (ny<1 || ny>N || nx<1 || nx>N) {
totalOutSand = totalOutSand + movedSand;
continue;
}
//경계 벗어나지 않으면 기존map[ny][nx] + 날아온 모래량
map[ny][nx] = map[ny][nx] + movedSand;
}
map[y][x] = 0;
//SandPrint(y,x);
//cout << "totalOutSand: " << totalOutSand << "\n";
}
int ChangeDir(int dir) {
int ndir = (dir + 1) % 4;
return ndir;
}
void MoveTonado(int y, int x) {
int ny = y;
int nx = x;
int distance = 1;
int dir = 0; //서쪽 움직임으로 시작
while (1) {
if (distance == N) { //만약 N만큼 움직여야한다면 N-1만큼 움직이고 끝
distance -= 1;
break;
}
//같은 거리로 두번 움직이되, 한번 총거리 움직일때 마다 방향 바꾸기
for (int i = 0; i < 2; i++) {
for (int j = 1; j <= distance; j++) {
ny = ny + dy[dir];
nx = nx + dx[dir];
//BeforePrint();
SpreadSand(ny, nx, dir);
}
//Print();
dir = ChangeDir(dir); //거리만큼 움직였으면 방향바꾸기
}
distance++; //같은 거리 두번 움직이면 거리 + 1
}
//마지막 거리 움직임 표현
for (int j = 1; j <= distance; j++) {
ny = ny + dy[dir];
nx = nx + dx[dir];
//BeforePrint();
SpreadSand(ny, nx, dir);
//MoveTest(ny, nx);
}
//Print();
}
void Input() {
cin >> N;
for (int i = 1; i <= N; i++) {
for (int j = 1; j <= N; j++) {
int tmp;
cin >> tmp;
map[i][j] = tmp;
}
}
}
int main() {
Input();
y = (N + 1) / 2;
x = (N + 1) / 2;
MoveTonado(y,x);
//cout << "result: " << totalOutSand<<"\n";
cout << totalOutSand;
}

다시 풀어본 횟수 : 0
- 다시 풀때 고려해 볼 점
**토네이도가 이동할 곳의 모래가 0일때, 즉 없는 경우에는 비율계산을 할 필요가 없다!