[알고리즘][X] 술래 잡기
2024. 4. 9. 17:57ㆍ알고리즘 풀이/Java
코드트리 | 코딩테스트 준비를 위한 알고리즘 정석
국가대표가 만든 코딩 공부의 가이드북 코딩 왕초보부터 꿈의 직장 코테 합격까지, 국가대표가 엄선한 커리큘럼으로 준비해보세요.
www.codetree.ai
import java.awt.Point;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
import java.util.StringTokenizer;
public class Main {
static class Node{
Point point;
Point dir;
public Node(Point point, Point dir) {
super();
this.point = point;
this.dir = dir;
}
@Override
public String toString() {
return "Node [point=" + point + ", dir=" + dir + "]";
}
}
static int n;
static int m;
static int h;
static int k;
static int[][] runner;
static boolean[][] tree;
static int[] dx = {1, 0, 0, -1};
static int[] dy = {0, 1, -1, 0};
static List<Node> res;
static int score;
public static void main(String[] args) throws Exception {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st = new StringTokenizer(br.readLine());
n = Integer.parseInt(st.nextToken());
m = Integer.parseInt(st.nextToken());
h = Integer.parseInt(st.nextToken());
k = Integer.parseInt(st.nextToken());
score = 0;
runner = new int[m][4];
tree = new boolean[n][n];
for (int i = 0; i < m; i++) {
st = new StringTokenizer(br.readLine());
for (int j = 0; j < 2; j++) {
runner[i][j] = Integer.parseInt(st.nextToken()) - 1;
}
int dir = Integer.parseInt(st.nextToken());
if (dir == 1) {
runner[i][2] = 1;
} else {
runner[i][2] = 0;
}
}
for (int i = 0; i < h; i++) {
st = new StringTokenizer(br.readLine());
int x = Integer.parseInt(st.nextToken()) - 1;
int y = Integer.parseInt(st.nextToken()) - 1;
tree[x][y] = true;
}
res = new ArrayList<>();
res.add(new Node(new Point(n/2, n/2), new Point(-1, 0)));
res.addAll(forward(n));
res.addAll(backward(n));
// System.out.println(res);
for (int i = 0; i < k; i++) {
playGame(i);
}
System.out.println(score);
}
private static void playGame(int t) {
for (int i = 0; i < m; i++) {
if (runner[i][3] == 1) {
continue;
}
int x = runner[i][0];
int y = runner[i][1];
int dir = runner[i][2];
Node node = res.get(t % res.size());
Point cur = node.point;
int dist = Math.abs(cur.x - x) + Math.abs(cur.y - y);
if (dist <= 3) {
int nx = x + dx[dir];
int ny = y + dy[dir];
if (!(0 <= nx && nx < n && 0 <= ny && ny < n)) {
dir = 3 - dir;
nx = x + dx[dir];
ny = y + dy[dir];
runner[i][2] = dir;
}
if (!(cur.x == nx && cur.y == ny)) {
runner[i][0] = nx;
runner[i][1] = ny;
}
}
}
Node node = res.get((t+1) % res.size());
Point cur = node.point;
Point dir = node.dir;
int nx = cur.x;
int ny = cur.y;
for (int k = 0; k < 3; k++) {
if (!(0 <= nx && nx <n && 0 <= ny && ny < n)) {
break;
}
if (tree[nx][ny]) {
nx += dir.x;
ny += dir.y;
continue;
}
for (int i = 0; i < m; i++) {
if (runner[i][3] == 1) {
continue;
}
if (nx == runner[i][0] && ny == runner[i][1]) {
score += (t+1);
runner[i][3] = 1;
}
}
nx += dir.x;
ny += dir.y;
}
// System.out.println(score);
}
private static List<Node> forward(int n) {
List<Node> queue = new ArrayList<>();
int[] dx = { -1, 0, 1, 0 };
int[] dy = { 0, 1, 0, -1 };
Point cur = new Point(n / 2, n / 2);
int step = 0;
int nx = cur.x;
int ny = cur.y;
out: while (true) {
// 순방향
for (int i = 0; i < 4; i++) {
if (i % 2 == 0) {
step++;
}
for (int j = 0; j < step; j++) {
nx += dx[i];
ny += dy[i];
if (nx == 0 && ny == 0) {
Node node = new Node(new Point(nx, ny), new Point(1, 0));
queue.add(node);
break out;
}
Node node;
if (j == step -1) {
node = new Node(new Point(nx, ny), new Point(dx[(i+1)%4], dy[(i+1)%4]));
} else {
node = new Node(new Point(nx, ny), new Point(dx[i%4], dy[i%4]));
}
queue.add(node);
}
}
}
return queue;
}
private static List<Node> backward(int n) {
List<Node> queue = new ArrayList<>();
int[] dx = {0, -1, 0, 1};
int[] dy = {1, 0, -1, 0};
Point cur = new Point(0, 0);
int step = n;
int nx = cur.x;
int ny = cur.y;
for (int i = 0; i < n - 1; i++) {
nx += 1;
Node node;
if (i == n - 2) {
node = new Node(new Point(nx, ny), new Point(0, 1));
}
else {
node = new Node(new Point(nx, ny), new Point(1, 0));
}
queue.add(node);
}
out: while (true) {
// 순방향
for (int i = 0; i < 4; i++) {
if (i % 2 == 0) {
step--;
}
for (int j = 0; j < step; j++) {
nx += dx[i];
ny += dy[i];
if (nx == n / 2 && ny == n /2) {
break out;
}
Node node;
if (j == step -1) {
node = new Node(new Point(nx, ny), new Point(dx[(i+1)%4], dy[(i+1)%4]));
} else {
node = new Node(new Point(nx, ny), new Point(dx[i%4], dy[i%4]));
}
queue.add(node);
}
}
}
return queue;
}
}
나의 풀이
- 술래의 위치를 순방향과 역방향으로 구분하여 구한 다음 concat해주었다. 그리고 각 시간마다 시간을 index로 하여 접근하여 값을 가져왔다.
- 디버깅이 안되는 부분이 있었는데 끝점에서 예외처리하는 부분에서 방향을 바꾸어 주어야 했는데 안해주었다.
- 또한 도망자의 그 다음 위치를 구할 때 nx = x + dx[dir]을 해야 하는데 술래의 위치를 기준으로 바꾸어 주어 틀렸었다.
'알고리즘 풀이 > Java' 카테고리의 다른 글
[알고리즘][X] 소수의 연속합 (0) | 2024.04.15 |
---|---|
[알고리즘][X] 계단 수 (0) | 2024.04.14 |
[알고리즘] 보급로 (0) | 2024.04.04 |
[알고리즘][X] 토끼와 경주 (2) | 2024.04.03 |
[알고리즘][X] 키 순서 (0) | 2024.04.03 |