Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 7543a9b

Browse files
committed
배수빈: [CT] 팩맨_241124
1 parent e42a49e commit 7543a9b

File tree

1 file changed

+232
-0
lines changed

1 file changed

+232
-0
lines changed

‎CodeTree/2021-2022년/SB_팩맨.java‎

Lines changed: 232 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,232 @@
1+
import java.io.BufferedReader;
2+
import java.io.IOException;
3+
import java.io.InputStreamReader;
4+
import java.util.*;
5+
6+
/*
7+
* 팩맨 게임: 몬스터의 복제, 이동, 팩맨의 이동, 시체 소멸, 몬스터 부화 단계를 구현
8+
*/
9+
public class st_팩맨 {
10+
static int M, T; // 몬스터 수, 턴 수
11+
static final int N = 4; // 격자 크기 (4x4)
12+
static Monster pacMan;
13+
static Queue<Monster> active = new ArrayDeque<>();
14+
static Queue<Monster> eggs = new ArrayDeque<>();
15+
static HashMap<Integer, Monster> liveInfo = new HashMap<>();
16+
static List<List<Integer>> board = new ArrayList<>();
17+
static int[] ghost = new int[N * N]; // 시체 시간 기록
18+
static int idx = 0; // 몬스터 ID
19+
static int time; // 현재 턴
20+
static int[] dx = {-1, -1, 0, 1, 1, 1, 0, -1};
21+
static int[] dy = {0, -1, -1, -1, 0, 1, 1, 1};
22+
static int mx; // 팩맨이 먹은 최대 몬스터 수
23+
static Monster tmpPac; // 팩맨 임시 위치
24+
static Set<Integer> eatMon; // 팩맨이 먹은 몬스터 위치
25+
26+
27+
// 몬스터 복제 시도
28+
private static void duplicate() {
29+
for (Monster mon : liveInfo.values()) {
30+
eggs.offer(new Monster(++idx, mon.r, mon.c, mon.d));
31+
}
32+
}
33+
34+
// 몬스터 이동
35+
private static void moveMonsters() {
36+
int pacPos = getPos(pacMan.r, pacMan.c); // 팩맨 위치
37+
int size = active.size();
38+
39+
for (int i = 0; i < size; i++) {
40+
Monster cur = active.poll();
41+
int curPos = getPos(cur.r, cur.c);
42+
boolean moved = false;
43+
44+
for (int j = 0; j < 8; j++) {
45+
int nd = (cur.d + j) % 8;
46+
int nr = cur.r + dx[nd];
47+
int nc = cur.c + dy[nd];
48+
int newPos = getPos(nr, nc);
49+
50+
if (isValid(nr, nc) && newPos != pacPos && ghost[newPos] == 0) {
51+
cur.move(nr, nc, nd);
52+
board.get(curPos).remove(Integer.valueOf(cur.idx));
53+
board.get(newPos).add(cur.idx);
54+
active.offer(cur);
55+
moved = true;
56+
break;
57+
}
58+
}
59+
60+
if (!moved) { // 움직이지 않았으면 다시 활동큐에 넣기
61+
active.offer(cur);
62+
}
63+
}
64+
}
65+
66+
// 팩맨 이동
67+
private static void movePac() {
68+
mx = -1;
69+
tmpPac = new Monster(0, pacMan.r, pacMan.c, 0);
70+
71+
for (int i = 0; i < 8; i += 2) {
72+
List<Integer> tmp = new ArrayList<>();
73+
Monster tPac = new Monster(0, pacMan.r, pacMan.c, i);
74+
dfs(0, tPac, tmp, 0);
75+
}
76+
77+
for (int pos : eatMon) {
78+
List<Integer> lst = board.get(pos);
79+
Iterator<Integer> itr = lst.iterator();
80+
while (itr.hasNext()) {
81+
int mon = itr.next();
82+
liveInfo.remove(mon);
83+
ghost[pos] = time;
84+
itr.remove();
85+
}
86+
}
87+
88+
pacMan.move(tmpPac.r, tmpPac.c, tmpPac.d);
89+
}
90+
91+
// DFS로 팩맨의 최적 경로 탐색
92+
private static void dfs(int depth, Monster tPac, List<Integer> tmp, int cnt) {
93+
if (depth == 3) {
94+
if (cnt > mx) {
95+
mx = cnt;
96+
eatMon = new HashSet<>(tmp); // 최종 먹은 몬스터 위치 저장
97+
tmpPac = new Monster(tPac.idx, tPac.r, tPac.c, tPac.d);
98+
}
99+
return;
100+
}
101+
102+
int od = tPac.d; // 원래 방향 저장
103+
for (int i = 0; i < 8; i += 2) {
104+
int nr = tPac.r + dx[i];
105+
int nc = tPac.c + dy[i];
106+
if (!isValid(nr, nc)) continue;
107+
108+
int pos = getPos(nr, nc);
109+
int addCnt = 0;
110+
111+
if (!tmp.contains(pos)) { // 중복된 위치는 다시 먹지 않음
112+
addCnt = board.get(pos).size();
113+
if (addCnt > 0) tmp.add(pos); // 먹은 곳의 위치 추가
114+
}
115+
116+
tPac.move(nr, nc, i); // 팩맨 이동
117+
dfs(depth + 1, tPac, tmp, cnt + addCnt);
118+
tPac.move(tPac.r - dx[i], tPac.c - dy[i], od); // 팩맨 위치 복구
119+
120+
if (addCnt > 0) tmp.remove(tmp.size() - 1); // 방문 기록 복구
121+
}
122+
}
123+
124+
125+
// 시체 소멸
126+
private static void clearGhosts() {
127+
for (int i = 0; i < N * N; i++) {
128+
if (time - ghost[i] > 2) {
129+
ghost[i] = 0;
130+
}
131+
}
132+
}
133+
134+
// 몬스터 부화
135+
private static void hatchingEggs() {
136+
while (!eggs.isEmpty()) {
137+
Monster mon = eggs.poll();
138+
liveInfo.put(mon.idx, mon);
139+
board.get(getPos(mon.r, mon.c)).add(mon.idx);
140+
active.offer(mon);
141+
}
142+
}
143+
144+
// 유효한 위치 확인
145+
private static boolean isValid(int r, int c) {
146+
return 0 <= r && r < N && 0 <= c && c < N;
147+
}
148+
149+
// 2차원 좌표를 1차원 인덱스로 변환
150+
private static int getPos(int r, int c) {
151+
return r * N + c;
152+
}
153+
154+
public static void main(String[] args) throws IOException {
155+
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
156+
StringTokenizer st = new StringTokenizer(br.readLine());
157+
158+
M = Integer.parseInt(st.nextToken());
159+
T = Integer.parseInt(st.nextToken());
160+
161+
st = new StringTokenizer(br.readLine());
162+
int pr = Integer.parseInt(st.nextToken()) - 1;
163+
int pc = Integer.parseInt(st.nextToken()) - 1;
164+
pacMan = new Monster(0, pr, pc, 0);
165+
166+
// 보드 초기화
167+
for (int i = 0; i < N * N; i++) {
168+
board.add(new ArrayList<>());
169+
}
170+
171+
for (int i = 0; i < M; i++) {
172+
st = new StringTokenizer(br.readLine());
173+
int r = Integer.parseInt(st.nextToken()) - 1;
174+
int c = Integer.parseInt(st.nextToken()) - 1;
175+
int d = Integer.parseInt(st.nextToken()) - 1;
176+
177+
Monster monster = new Monster(++idx, r, c, d);
178+
liveInfo.put(idx, monster);
179+
active.offer(monster);
180+
board.get(getPos(r, c)).add(monster.idx);
181+
}
182+
183+
time = 1;
184+
while (T-- > 0) {
185+
// 1. 몬스터 복제 시도
186+
duplicate();
187+
188+
// 2. 몬스터 이동
189+
moveMonsters();
190+
191+
// 3. 팩맨 이동
192+
movePac();
193+
194+
// 4. 시체 소멸
195+
clearGhosts();
196+
197+
// 5. 몬스터 부화
198+
hatchingEggs();
199+
200+
time++;
201+
}
202+
203+
System.out.println(liveInfo.size());
204+
}
205+
206+
static class Monster {
207+
int idx, r, c, d;
208+
209+
Monster(int idx, int r, int c, int d) {
210+
this.idx = idx;
211+
this.r = r;
212+
this.c = c;
213+
this.d = d;
214+
}
215+
216+
void move(int r, int c, int d) {
217+
this.r = r;
218+
this.c = c;
219+
this.d = d;
220+
}
221+
222+
@Override
223+
public String toString() {
224+
return "Monster{" +
225+
"idx=" + idx +
226+
", r=" + r +
227+
", c=" + c +
228+
", d=" + d +
229+
'}';
230+
}
231+
}
232+
}

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /