Java/코딩테스트
백준 23290
Bubbles
2023. 4. 8. 23:25
결국 3차원 배열로 풀어야 했던 문제..
🐟 같은 방향 보고 있는 물고기 2마리 이상이 같은 칸에 존재할 수도 있다. 이걸 되게 고민했는데 3차원 배열 쓰는게 더 편한것 같다...
🐟그리고 계속 실수했던 부분이 냄새를 삭제하는거... 상어가 움직이기 전에 각 smell[][] 감소시켜줘야한다. 상어가 움직이고 나서 감소해주면 갱신된 상태에서 감소시키는거라 계속 답이 틀림
진짜 너무 복잡했다... ㅎ
아직 코딩 멀었다~.~...
🐟 변수
temp는 방향까지 저장한 것
fishAmountMap은 단순 해당 좌표에 몇마리 있는지만 저장한 것 (상어가 먹을 때는 방향상관없이 같은 칸에 있는거 다먹으니까)
static int m, s;
// 물고기의 8방향
public static int[] fishX= {0, -1, -1, -1, 0, 1, 1, 1};
public static int[] fishY = {-1, -1, 0, 1, 1, 1, 0, -1};
// 상어의 4방향, 상좌하우 순서
public static int[] sharkX = {-1, 0, 1, 0};
public static int[] sharkY = {0, -1, 0, 1};
// 상어 현재 위치
static Pos shark;
static int answer;
// 가장 많이 먹을 수 있는 이동방향
static int[] maxEatWay;
// 물고기 총 마리 수
static int fishAmount;
// 각 칸 당 물고기 수
static int[][] fishAmountMap;
// 원본 배열, 마지막 단계에서 복제된 물고기 합쳐주기 위해 사용
static int[][][] map = new int[4][4][8];
// 냄새 배열, 상어가 지나간 자리는 2로 만든다.
static int[][] smell = new int[4][4];
// 물고기 이동시마다 temp를 초기화하여 사용, 상어이동까지 끝나면 temp와 map을 합침
static int[][][] temp;
🐟 로직 순서
물고기 움직이기(여기서 temp 배열 만든다)
상어가 가장 많이 먹을 수 있는 방법, 먹을 수 있는 물고기 수 초기화
냄새 제거
상어의 경로 탐색
상어 실제로 움직이기
temp와 map 합치기
public static void magic() {
fishMove();
maxEatWay = new int[3];
fishAmount = -11;
removeSmell();
findSharkWay();
sharkMove();
mergeArray();
}
1. 물고기 움직이기
public static void fishMove() {
fishAmountMap = new int[4][4];
temp = new int[4][4][8];
// 모든 칸에 대해
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) {
// 8방향 탐색 시작
for (int d = 0; d < 8; d++) {
if (map[i][j][d] == 0) {
continue;
// i, j 칸에 d 방향의 물고기는 없다는 뜻
} else {
int tempDir = d;
while (true) {
int nextX = i + fishX[tempDir];
int nextY = j + fishY[tempDir];
if (!isValid(nextX, nextY)
|| smell[nextX][nextY] > 0
|| (nextX == shark.x && nextY == shark.y)) {
tempDir--; // 반시계방향으로 돌기 때문에 -1
if (tempDir == -1) {
tempDir = 7;
}
// 탐색 다 해봤는데도 안나와서 원래 방향으로 돌아온 케이스
// 오리지널 맵에서 다시 데이터 꺼내와서 저장
if (tempDir == d) {
temp[i][j][d] += map[i][j][d];
fishAmountMap[i][j] += map[i][j][d];
break;
}
continue;
}
// 갈 수 있는 경우 현 위치의 것을 이동할 위치에다가 옮겨서 저장
temp[nextX][nextY][tempDir] += map[i][j][d];
fishAmountMap[nextX][nextY] += map[i][j][d];
break;
}
}
}
}
}
}
2. 냄새 없애기
public static void removeSmell() {
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) {
if (smell[i][j] > 0) {
smell[i][j]--;
}
}
}
}
3. 상어의 경로 찾기
maxEatWay = new int[3];
fishAmount = -11;
public static void findSharkWay() {
// 현재 상어 위치
int x = shark.x;
int y = shark.y;
// 먹은양
int eaten = 0;
// 총 3칸을 이동하므로 3중 for문을 4번씩 돌린다(4방향 탐색)
// 갔던 곳을 또 갈 수 있다. 이 때 물고기 카운트 중복해서 세면 안된다.
for (int i = 0; i < 4; i++) {
int firstX = x + sharkX[i];
int firstY = y + sharkY[i];
if (!isValid(firstX, firstY)) {
continue;
}
eaten += fishAmountMap[firstX][firstY];
for (int j = 0; j < 4; j++) {
int secondX = firstX + sharkX[j];
int secondY = firstY + sharkY[j];
if (!isValid(secondX, secondY)) {
continue;
}
eaten += fishAmountMap[secondX][secondY];
for (int k = 0; k < 4; k++) {
int thirdX = secondX + sharkX[k];
int thirdY = secondY + sharkY[k];
if (!isValid(thirdX, thirdY)) {
continue;
}
// 왔던 좌표가 아닌 경우에만 third 포지션의 물고기 먹기
if (firstX != thirdX || firstY != thirdY) {
eaten += fishAmountMap[thirdX][thirdY];
}
// 현재 경로가 더 많이 먹은거면 갱신후 그 방향들 저장
if (fishAmount < eaten) {
fishAmount = eaten;
maxEatWay[0] = i;
maxEatWay[1] = j;
maxEatWay[2] = k;
}
// 먹은거 차례로 빼주면서 최대값 찾기
if (firstX != thirdX || firstY != thirdY) {
eaten -= fishAmountMap[thirdX][thirdY];
}
}
eaten -= fishAmountMap[secondX][secondY];
}
eaten -= fishAmountMap[firstX][firstY];
}
}
4. 상어를 해당 경로대로 이동 시키며 먹기
상어 지나간 칸에 temp에 새로운 배열 할당하고, fishAmountMap 도 0으로 초기화, 냄새 남기기
public static void sharkMove() {
int x = shark.x;
int y = shark.y;
// 최대 물고기 먹을 수 있는 경로대로 상어 움직임
for (int i = 0; i < 3; i++) {
int dir = maxEatWay[i];
x += sharkX[dir];
y += sharkY[dir];
if (fishAmountMap[x][y] != 0) {
temp[x][y] = new int[8]; // 오리지널 맵 바로 조작하는거 아님!!
fishAmountMap[x][y] = 0;
smell[x][y] = 2;
}
}
// 다 먹으면 이동!
shark = new Pos(x, y);
}
5. 복사된 원본과 상어가 먹은 배열 합치기
public static void mergeArray() {
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) {
if (fishAmountMap[i][j] != 0) {
for (int d = 0; d < 8; d++) {
map[i][j][d] += temp[i][j][d];
}
}
}
}
}