[java,백준3190]뱀 - Deque를 활용한 뱀 이동 시뮬레이션
Deque 자료구조를 활용하여 뱀의 머리와 꼬리를 동시에 관리하며 이동을 시뮬레이션하는 문제입니다.
예시를 시각화 해보자
문제 1번 예시 시각화:
1초
[0, 1, 0, 0, 0, 0, 0]
[0, 0, 0, 0, 2, 0, 0]
[0, 0, 0, 2, 0, 0, 0]
[0, 0, 0, 0, 0, 0, 0]
[0, 0, 2, 0, 0, 0, 0]
[0, 0, 0, 0, 0, 0, 0]
...
5초
[0, 0, 0, 0, 0, 0, 0]
[0, 0, 0, 1, 2, 0, 0]
[0, 0, 0, 1, 0, 0, 0]
[0, 0, 0, 0, 0, 0, 0]
[0, 0, 2, 0, 0, 0, 0]
[0, 0, 0, 0, 0, 0, 0]
...
8초
[0, 0, 0, 0, 0, 0, 0]
[0, 0, 0, 0, 2, 0, 0]
[0, 0, 0, 0, 0, 0, 0]
[0, 0, 0, 0, 0, 0, 0]
[0, 0, 2, 1, 0, 0, 0]
[0, 0, 0, 1, 0, 0, 0]
9초 => 답
풀이
구현 시 주의사항
💡 뱀의 머리와 꼬리 이동을 동시에 처리해야 하는 자료구조를 생각하고, 방향 전환 시점을 정확히 체크해야 한다.
Deque로 뱀의 머리와 꼬리를 관리하고, 매 초마다 이동과 방향 전환을 처리
💡 항상 시뮬레이션 문제는 “디버깅 강추!”
핵심 구현 사항
- Deque를 사용한 뱀 관리 (머리, 꼬리 위주)
- 사과 먹기 처리
- 방향 전환 처리
- 충돌 체크 (벽, 자기자신)
뱀 이동 처리
-
nx<0||ny<0||nx>N-1||ny>N-1
: 충돌체크 - 벽 부딪 -
map[nx][ny]==1
: 충돌체크 - 뱀 몸 부딪 -
사과 유무 분기??
-
if map[nx][ny] == 2
: 사과 있다면??checkDir(time, head, qu);
처리 이후에 머리이동, 꼬리 그대로 로직 사용 -
else
: 사과 없다면?checkDir(time, head, qu);
처리 이후에 머리이동, 꼬리 1칸 제거 로직 사용
-
static void solve(Queue<Info> qu) {
Deque<Pair> dq = new ArrayDeque<>();
map[0][0] = 1;
dq.offer(new Pair(0, 0, 0));
while (true) {
// 머리 이동
Pair head = dq.peekFirst();
Pair tail = dq.peekLast();
int nx = head.x + dx[head.dir];
int ny = head.y + dy[head.dir];
// 충돌 체크
if(nx<0||ny<0||nx>N-1||ny>N-1) break; //벽 부딪
if(map[nx][ny]==1) break; //뱀 몸에 부딪
// 이동 처리
if (map[nx][ny] == 2) { // 사과가 있는 경우
//(중요)방향 전환 있나 체크 후 추가(dir 수정)
int dir = checkDir(time, head, qu);
map[nx][ny] = 1;
dq.offerFirst(new Pair(nx, ny, dir));
} else { // 사과가 없는 경우
//(중요)방향 전환 있나 체크 후 추가(dir 수정)
map[tail.x][tail.y] = 0;
dq.pollLast();
int dir = checkDir(time, head, qu);
map[nx][ny] = 1;
dq.offerFirst(new Pair(nx, ny, dir));
}
}
}
방향 전환 처리
- dir은 0~3 사이의 값을 가지기 때문에 해당 사이의 값을 가지게 로직을 구성
- 큐 제거로 null 에러 발생 방지 위해 main함수에서
qu.offer(new Info(9999999, 'X'));
필수
private static int checkDir(int time, Pair head, Queue<Info> qu) {
Info info = qu.peek();
int dir = head.dir;
if (info.x == time) {
if(info.c=='D') dir = (dir+1)%4;
if (info.c == 'L') {
if(dir-1 < 0) dir = 3;
else dir = dir-1;
}
qu.poll(); //큐 제거
}
return dir;
}
전체 코드
public class 뱀_3190 {
static int N, K, L;
static int[][] map; //약속 - 빈공간:0, 뱀:1, 사과:2
static int[] dx = {0, 1, 0, -1};
static int[] dy = {1, 0 ,-1, 0};
static int result;
static void solve(Queue<Info> qu) {
//init
Deque<Pair> dq = new ArrayDeque<>();
int time = 0;
map[0][0] = 1;
dq.offer(new Pair(0, 0, 0));
//run
while (true) {
time++;
Pair head = dq.peekFirst();
Pair tail = dq.peekLast();
int nx = head.x + dx[head.dir];
int ny = head.y + dy[head.dir];
//base condition
if(nx<0||ny<0||nx>N-1||ny>N-1) break; //벽 부딪
if(map[nx][ny]==1) break; //뱀 몸에 부딪
//run
if (map[nx][ny] == 2) { //사과 있다면? -> 머리이동, 꼬리 그대로
//(중요)방향 전환 있나 체크 후 기록(dir 수정)
int dir = checkDir(time, head, qu);
map[nx][ny] = 1;
dq.offerFirst(new Pair(nx, ny, dir));
} else { //사과 없다면? -> 머리이동, 꼬리 1칸 제거
//(중요)방향 전환 있나 체크 후 추가(dir 수정)
int dir = checkDir(time, head, qu);
map[tail.x][tail.y] = 0;
dq.pollLast();
map[nx][ny] = 1;
dq.offerFirst(new Pair(nx, ny, dir));
}
printAll(time); //debug
}
result = time;
}
private static void printAll(int time) {
System.out.println(time);
for (int i = 0; i < N; i++) {
System.out.println(Arrays.toString(map[i]));
}
System.out.println();
}
private static int checkDir(int time, Pair head, Queue<Info> qu) {
Info info = qu.peek();
int dir = head.dir;
if (info.x == time) {
if(info.c=='D') dir = (dir+1)%4;
if (info.c == 'L') {
if(dir-1 < 0) dir = 3;
else dir = dir-1;
}
qu.poll(); //큐 제거
}
return dir;
}
public static void main(String[] args) throws IOException {
//input
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
N = Integer.parseInt(br.readLine());
K = Integer.parseInt(br.readLine());
map = new int[N + 1][N + 1];
for (int i = 0; i < K; i++) {
StringTokenizer stk = new StringTokenizer(br.readLine(), " ");
int x = Integer.parseInt(stk.nextToken())-1;
int y = Integer.parseInt(stk.nextToken())-1; //-1 이유:좌표 1,1을 0,0으로 맞추기 위함
map[x][y] = 2; //사과:2
}
L = Integer.parseInt(br.readLine());
Queue<Info> qu = new ArrayDeque<>();
for (int i = 0; i < L; i++) {
StringTokenizer stk = new StringTokenizer(br.readLine(), " ");
qu.offer(new Info(Integer.parseInt(stk.nextToken()), stk.nextToken().charAt(0)));
}
qu.offer(new Info(9999999, 'X')); //큐 모두 제거로 null 에러 방지 위해
//run
solve(qu);
//output
System.out.println(result);
}
static class Pair{
int x; int y; int dir;
Pair(int x, int y, int dir) {
this.x=x; this.y=y; this.dir=dir;
}
}
static class Info{
int x; char c;
Info(int x, char c) {
this.x =x; this.c=c;
}
}
}
주관적인 생각의 풀이이므로 틀린 부분 지적은 언제나 환영합니다⚡
댓글남기기