ImplementationSimulation코드트리
https://www.codetree.ai/ko/frequent-problems/samsung-sw/problems/ai-robot/description
import java.io.*;
import java.util.*;
public class Main {
private static final int[] cy = new int[] { -1, 0, 1, 0 };// 상 우 하 좌
private static final int[] cx = new int[] { 0, 1, 0, -1 };
private static final int[] dy = new int[] { -1, 0, 0, 1 };// 상 좌 우 하
private static final int[] dx = new int[] { 0, -1, 1, 0 };
private static final int BLOCKED = -1;
private static final int CLEAN = 0;
private static final int MAXIMUM_CLEANING_AMOUNT = 20;
private static final int ACCUMULATING_DUST_AMOUNT = 5;
private static class Dust {
private int amount;
private boolean isPlacedRobot;
public Dust(int amount, boolean isPlacedRobot) {
this.amount = amount;
this.isPlacedRobot = isPlacedRobot;
}
}
private static List<int[]> robotsPosition = new ArrayList<>();
private static StringBuilder answer = new StringBuilder();
private static int N, K, L;
private static Dust[][] map;
public static void main(String[] args) throws IOException {
init();
sol();
print();
}
private static void sol() {
while (L-- > 0) {
moveRobots();
clean();
accumulateDust();
spreadDust();
calculateWholeDustAmount();
}
}
private static void calculateWholeDustAmount() {
int wholeDustAmount = 0;
for (int i = 1; i <= N; i++) {
for (int j = 1; j <= N; j++) {
if (map[i][j].amount > CLEAN) {
wholeDustAmount += map[i][j].amount;
}
}
}
answer.append(wholeDustAmount).append("\n");
}
private static void spreadDust() {
int[][] addMap = new int[N + 1][N + 1];
for (int i = 1; i <= N; i++) {
for (int j = 1; j <= N; j++) {
if (map[i][j].amount == CLEAN) {
int dustAmount = 0;
for (int k = 0; k < 4; k++) {
int py = i + dy[k];
int px = j + dx[k];
if (isOutOfRange(py, px) || map[py][px].amount == BLOCKED) {
continue;
}
dustAmount += map[py][px].amount;
}
addMap[i][j] = dustAmount / 10;
}
}
}
for (int i = 1; i <= N; i++) {
for (int j = 1; j <= N; j++) {
map[i][j].amount += addMap[i][j];
}
}
}
private static void accumulateDust() {
for (int i = 1; i <= N; i++) {
for (int j = 1; j <= N; j++) {
if (map[i][j].amount > CLEAN) {
map[i][j].amount += ACCUMULATING_DUST_AMOUNT;
}
}
}
}
private static void clean() {
for (int[] robotPosition : robotsPosition) {
List<int[]> maximumCleaningAmountArea = getMaximumCleaningAmounArea(robotPosition[0], robotPosition[1]);
for (int[] cleaningArea : maximumCleaningAmountArea) {
int y = cleaningArea[0];
int x = cleaningArea[1];
if (map[y][x].amount > MAXIMUM_CLEANING_AMOUNT) {
map[y][x].amount -= MAXIMUM_CLEANING_AMOUNT;
} else {
map[y][x].amount = CLEAN;
}
}
}
}
private static List<int[]> getMaximumCleaningAmounArea(int currentY, int currentX) {
List<int[]> maximumCleaningAmountArea = new ArrayList<>();
int maximumCleaningAmount = Integer.MIN_VALUE;
int index = 0;
for (int i = 0; i < 4; i++) {
List<int[]> cleaningArea = new ArrayList<>();
int cleaningAmount = 0;
int idx = index;
cleaningArea.add(new int[] { currentY, currentX });
for (int j = 0; j < 3; j++) {
int nextY = currentY + cy[idx];
int nextX = currentX + cx[idx];
if (isOutOfRange(nextY, nextX) || map[nextY][nextX].amount == BLOCKED) {
idx = idx + 1 > 3 ? 0 : idx + 1;
continue;
}
cleaningAmount += map[nextY][nextX].amount > MAXIMUM_CLEANING_AMOUNT
? MAXIMUM_CLEANING_AMOUNT
: map[nextY][nextX].amount;
cleaningArea.add(new int[] { nextY, nextX });
idx = idx + 1 > 3 ? 0 : idx + 1;
}
if (maximumCleaningAmount < cleaningAmount) {
maximumCleaningAmount = cleaningAmount;
maximumCleaningAmountArea = cleaningArea;
}
index++;
}
return maximumCleaningAmountArea;
}
private static void moveRobots() {
List<int[]> newRobotsPosition = new ArrayList<>();
for (int[] robotPosition : robotsPosition) {
int currentY = robotPosition[0];
int currentX = robotPosition[1];
if (map[currentY][currentX].amount > CLEAN) {
newRobotsPosition.add(new int[] { currentY, currentX });
continue;
}
int[] nextPosition = bfs(currentY, currentX);
if (nextPosition.length != 0) {
int nextY = nextPosition[0];
int nextX = nextPosition[1];
newRobotsPosition.add(new int[] { nextY, nextX });
map[currentY][currentX].isPlacedRobot = false;
map[nextY][nextX].isPlacedRobot = true;
} else {
newRobotsPosition.add(new int[] { currentY, currentX });
}
}
robotsPosition = newRobotsPosition;
}
private static int[] bfs(int currentY, int currentX) {
if (map[currentY][currentX].amount > CLEAN) {
return new int[] { currentY, currentX };
}
Deque<int[]> q = new ArrayDeque<>();
boolean[][] visited = new boolean[N + 1][N + 1];
q.offer(new int[] { currentY, currentX, 0 });
visited[currentY][currentX] = true;
int minY = Integer.MAX_VALUE;
int minX = Integer.MAX_VALUE;
int minDist = Integer.MAX_VALUE;
while (!q.isEmpty()) {
int[] current = q.poll();
int y = current[0];
int x = current[1];
int dist = current[2];
if (dist > minDist) {
break;
}
if (map[y][x].amount > CLEAN && !map[y][x].isPlacedRobot) {
if (dist < minDist) {
minDist = dist;
minY = y;
minX = x;
} else if (dist == minDist) {
if (y < minY || (y == minY && x < minX)) {
minY = y;
minX = x;
}
}
continue;
}
for (int i = 0; i < 4; i++) {
int nextY = y + dy[i];
int nextX = x + dx[i];
if (isOutOfRange(nextY, nextX)
|| visited[nextY][nextX]
|| map[nextY][nextX].isPlacedRobot == true
|| map[nextY][nextX].amount == BLOCKED) {
continue;
}
q.offer(new int[] { nextY, nextX, dist + 1 });
visited[nextY][nextX] = true;
}
}
if (minDist != Integer.MAX_VALUE) {
return new int[] { minY, minX };
}
return new int[] {};
}
private static boolean isOutOfRange(int y, int x) {
return y <= 0 || x <= 0 || y > N || x > N;
}
private static void init() throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st;
st = new StringTokenizer(br.readLine());
N = Integer.parseInt(st.nextToken());// 격자 크기
K = Integer.parseInt(st.nextToken());// 로봇 청소기의 개수
L = Integer.parseInt(st.nextToken());// 테스트 횟수
map = new Dust[N + 1][N + 1];
for (int i = 1; i <= N; i++) {
st = new StringTokenizer(br.readLine());
for (int j = 1; j <= N; j++) {
map[i][j] = new Dust(Integer.parseInt(st.nextToken()), false);
}
}
for (int i = 1; i <= K; i++) {
st = new StringTokenizer(br.readLine());
int y = Integer.parseInt(st.nextToken());
int x = Integer.parseInt(st.nextToken());
robotsPosition.add(new int[] { y, x });
map[y][x].isPlacedRobot = true;
}
}
private static void print() throws IOException {
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
bw.write(String.valueOf(answer));
bw.close();
}
}주요 개념
구현
시뮬레이
주의할 점
각각의 로봇 청소기는 순서대로 이동 거리가 가장 가까운 오염된 격자로 이동합니다.로봇 청소기의 이동 방법이 정의되어 있지 않지만 상하좌우로만 이동이 가능하도록 생각한다.
초기값으로는 로봇 청소기 밑에는 먼지가 없지만, 두 번째 이동부터는 아래에 먼지가 있을 수 있다.
즉, 이동하지 않을 수도 있다.
또한 가장 가까운 오염된 격자가 없는 경우에 대한 처리가 나와있지 않다.
동일하게 이동하지 않는 경우로 처리했다.