https://www.acmicpc.net/problem/8972
풀이
플레이어의 이동 명령만큼 1~6을 반복, 미친 아두이노와 플레이어 아두이노가 겹치면 게임 종료
1. 종수(플레이어) 이동
2. 이동 횟수 ++
3. 플레이어가 죽었는지 확인
4. 미친 아두이노 이동
5. 플레이어가 죽었는지 확인
6. 겹치는 미친 아두이누 폭발
미친 아두이노의 위치 정보를 2차원 배열 List와 List를 이용해 관리
static List<Integer>[][] map;
static List<Pos> crazyArduinos = new ArrayList<>();
static Pos player;
static class Pos {
int y, x, num;
Pos(int y, int x) {
this.y = y;
this.x = x;
this.num = -1;
}
Pos(int y, int x, int num) {
this.y = y;
this.x = x;
this.num = num;
}
}
플레이어 이동
플레이어와 아두이노의 이동 방향 결정 0 : 안씀, 5 : 위치 그대로
static int[] dy = {0, 1, 1, 1, 0, 0, 0, -1, -1, -1};
static int[] dx = {0, -1, 0, 1, -1, 0, 1, -1, 0, 1};
입력받은 이동 명령에 따라 다음 위치를 결정
private static void playerGo(int command) {
if (command == 5)
return;
player.y = player.y + dy[command];
player.x = player.x + dx[command];
}
플레이어가 죽었는지 확인
미친 아두이노가 있는 위치를 나타내는 2차원 배열 List에 플레이어의 위치를 대입
사이즈가 0이 아니라면 해당 위치에 미친 아두이노가 있기 때문에 게임오버
private static boolean isPlayerDead() {
if (map[player.y][player.x].size() == 0) return false;
else return true;
}
미친 아두이노 이동
이차원 배열 List의 모든 기록 삭제
List에 담긴 미친 아두이노의 현재위치를 순회하여 미친 아두이노의 다음 위치 결정
closetChoice()함수로 플레이어와 가장 가까운 위치를 향하는 방향을 결정
해당 방향으로 이동 - List에 담긴 미친 아두이노의 현재위치 수정, 이차원 배열 List의 위치에 add
private static void CrazyGo() {
for (int i = 0; i < R; i++) {
for (int j = 0; j < C; j++) {
map[i][j].clear();
}
}
for (int i = 0; i < crazyArduinos.size(); i++) {
int y = crazyArduinos.get(i).y;
int x = crazyArduinos.get(i).x;
int dir = closestChoice(y, x);
int ny = y + dy[dir];
int nx = x + dx[dir];
crazyArduinos.get(i).y = ny;
crazyArduinos.get(i).x = nx;
map[ny][nx].add(crazyArduinos.get(i).num);
}
}
미친 아두이노의 현재 위치를 매개변수로 플레이어와 가장 가까운 위치를 향하는 방향을 결정
상하좌우, 대각 8가지 방향에 대한 다음위치와 플레이어의 위치의 거리를 계산하여 가장 가까운 거리를 가진 방향을 return
private static int closestChoice(int y, int x) {
int minDist = 987654321;
int minDir = 0;
for (int dir = 1; dir <= 9; dir++) {
if (dir == 5) continue;
int ny = y + dy[dir];
int nx = x + dx[dir];
int dist = Math.abs(ny - player.y) + Math.abs(nx - player.x);
if (minDist > dist) {
minDist = dist;
minDir = dir;
}
return minDir
}
겹치는 아두이노 폭발
미친 아두이노의 위치정보가 담긴 List clear, 이차원 배열 List의 모든 위치를 탐색
현재 위치의 사이즈가 1이라면 겹치는 아두이노가 없기 때문에 정보 그대로 -> List에 add
현재 위치의 사이즈가 2이상이라면 겹치는 아두이노가 있기 때문에 해당 미친 아두이노를 삭제해야함
-> 2차원 배열 List의 현재 위치를 clear
private static void bombCrazy() {
crazyArduinos.clear();
for (int i = 0; i < R; i++) {
for (int j = 0; j < C; j++) {
if (map[i][j].size() == 1) crazyArduinos.add(new Pos(i, j, map[i][j].get(0)));
else if (map[i][j].size() >= 2) map[i][j].clear();
}
}
}
전체 코드
import java.io.*;
import java.util.*;
public class Main {
static int R, C;
static List<Integer>[][] map;
static int[] dy = {0, 1, 1, 1, 0, 0, 0, -1, -1, -1};
static int[] dx = {0, -1, 0, 1, -1, 0, 1, -1, 0, 1};
static List<Pos> crazyArduinos = new ArrayList<>();
static Pos player;
static class Pos {
int y, x, num;
Pos(int y, int x) {
this.y = y;
this.x = x;
this.num = -1;
}
Pos(int y, int x, int num) {
this.y = y;
this.x = x;
this.num = num;
}
}
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
// BufferedReader br = new BufferedReader(new FileReader("a.txt"));
StringTokenizer st = new StringTokenizer(br.readLine());
R = Integer.parseInt(st.nextToken());
C = Integer.parseInt(st.nextToken());
map = new ArrayList[R][C];
int arduinoIdx = 1;
for (int i = 0; i < R; i++) {
char[] temp = br.readLine().toCharArray();
for (int j = 0; j < temp.length; j++) {
map[i][j] = new ArrayList<Integer>();
if (temp[j] == 'I') {
player = new Pos(i, j);
} else if (temp[j] == 'R') {
crazyArduinos.add(new Pos(i, j, arduinoIdx));
map[i][j].add(arduinoIdx++);
}
}
}
char[] commands = br.readLine().toCharArray();
int cnt = 0;
for (char c : commands) {
playerGo(c - '0');
cnt++;
if (isPlayerDead()) break;
CrazyGo();
if (isPlayerDead()) break;
bombCrazy();
}
if (cnt < commands.length) {
System.out.println("kraj " + cnt);
} else {
printMap();
}
}
private static void printMap() {
char arr[][] = new char[R][C];
for (int i = 0; i < R; i++) {
Arrays.fill(arr[i], '.');
}
arr[player.y][player.x] = 'I';
for (Pos p : crazyArduinos) {
arr[p.y][p.x] = 'R';
}
for (int i = 0; i < R; i++) {
System.out.println(arr[i]);
}
}
// 겹치는 미친 아두이노 폭발
private static void bombCrazy() {
crazyArduinos.clear();
for (int i = 0; i < R; i++) {
for (int j = 0; j < C; j++) {
if (map[i][j].size() == 1) crazyArduinos.add(new Pos(i, j, map[i][j].get(0)));
else if (map[i][j].size() >= 2) map[i][j].clear();
}
}
}
// 미친 아두이노 이동
private static void CrazyGo() {
for (int i = 0; i < R; i++) {
for (int j = 0; j < C; j++) {
map[i][j].clear();
}
}
for (int i = 0; i < crazyArduinos.size(); i++) {
int y = crazyArduinos.get(i).y;
int x = crazyArduinos.get(i).x;
int dir = closestChoice(y, x);
int ny = y + dy[dir];
int nx = x + dx[dir];
crazyArduinos.get(i).y = ny;
crazyArduinos.get(i).x = nx;
map[ny][nx].add(crazyArduinos.get(i).num);
}
}
// 미친 아두이노가 플레이어와 가까워지는 방향 탐색
private static int closestChoice(int y, int x) {
int minDist = 987654321;
int minDir = 0;
for (int dir = 1; dir <= 9; dir++) {
if (dir == 5) continue;
int ny = y + dy[dir];
int nx = x + dx[dir];
int dist = Math.abs(ny - player.y) + Math.abs(nx - player.x);
if (minDist > dist) {
minDist = dist;
minDir = dir;
}
}
return minDir;
}
// 플레이어 이동
private static void playerGo(int command) {
if (command == 5)
return;
player.y = player.y + dy[command];
player.x = player.x + dx[command];
}
// 플레이어가 죽었는지 확인
// 플레이어의 위치와 같은 위치인 미친 아두이노가 있는지 탐색
private static boolean isPlayerDead() {
if (map[player.y][player.x].size() == 0) return false;
else return true;
}
}
'알고리즘' 카테고리의 다른 글
Programmers - 신고 결과 받기(Java) (0) | 2022.01.21 |
---|---|
Programmers - 수식 최대화(Java) (0) | 2022.01.17 |
BOJ 23289 - 온풍기 안녕(Java) (0) | 2022.01.12 |
BOJ 20058 - 마법사 상어와 파이어 스톰(Java) (0) | 2022.01.08 |
BOJ 16985 - Maaaaaaaaaze(Java) (0) | 2022.01.06 |
댓글