[java]새로운 게임 2 - 백준17837
문제
풀이
문제 해석을 하자면,
- 체스판의 크기와 말의 위치, 이동 방향이 모두 주어졌을 때, 게임이 종료되는 턴의 번호를 구하라.
풀이
- 시간초과를 조심해서 단순히 구현을 하면 되는 문제이다.
- 다만, 생각보다 구현이 까다로웠다.
- 1~K번말 “순서대로” 이동 을 지키기 위해
horse
배열에 따로 2차원배열 좌표값을 기록해갔다. - 그리고
map
배열에 색상을 기록해두고,inArr
배열에 실제 문제의 그림처럼 자료구조를 이어갔다. - 마지막으로 “말을 이동”할 때 꼭 해당 말부터 쌓인 말들 통째로 이동하게끔 구현해야한다.
코드
public static int N, K;
public static int result;
public static List<Pair>[][] inArr = new ArrayList[15][15];
public static int[][] map = new int[15][15];
public static Pair[] horse = new Pair[12];
public static int[] dx = {0, 0, -1, 1};
public static int[] dy = {1, -1, 0, 0};
public static int[] redir = {1, 0, 3, 2}; // 반대방향
public static void moveWhite(int nx, int ny, int idx) {
// 통째로 옮기는 작업
Pair p = horse[idx];
int findIdx = 0; // 말이 쌓여있을때 몇번째에 있는지 찾기 (num:순번)
int cx = p.x; int cy = p.y; // p.x, p.y 는 주소값으로 변경될 수 있어서 따로 복제해서 사용 (중요)
int size = inArr[cx][cy].size();
for(int i=0; i<size; i++) {
if(inArr[cx][cy].get(i).num == p.num) {
findIdx = i; break;
}
}
for(int i=findIdx; i<size; i++) { // findIdx부터 통째로 이동
horse[inArr[cx][cy].get(i).num].x = nx; //update 좌표
horse[inArr[cx][cy].get(i).num].y = ny;
inArr[nx][ny].add(inArr[cx][cy].get(i)); //add
inArr[cx][cy].remove(i); //delete
i--; //원복 -> 다음 배열인덱스 접근 위해 필수!
size--;
}
//debug
// for(int i=0; i<N; i++) {
// System.out.println(Arrays.toString(inArr[i]));
// }
// System.out.println("moveWhite");
}
public static void moveRed(int nx, int ny, int idx) {
// 통째로 옮기는 작업
Pair p = horse[idx];
int findIdx = 0; // 말이 쌓여있을때 몇번째에 있는지 찾기 (num:순번)
int cx = p.x; int cy = p.y; // p.x, p.y 는 주소값으로 변경될 수 있어서 따로 복제해서 사용 (중요)
int size = inArr[cx][cy].size();
for(int i=0; i<size; i++) {
if(inArr[cx][cy].get(i).num == p.num) {
findIdx = i; break;
}
}
for(int i=size-1; i>=findIdx; i--) { // 뒤쪽부터 넣음으로써 순서 반대 효과
horse[inArr[cx][cy].get(i).num].x = nx; //update 좌표
horse[inArr[cx][cy].get(i).num].y = ny;
inArr[nx][ny].add(inArr[cx][cy].get(i)); //add
inArr[cx][cy].remove(i); //delete
//뒤부터 삭제하므로 원복작업이 필요없음
}
//debug
// for(int i=0; i<N; i++) {
// System.out.println(Arrays.toString(inArr[i]));
// }
// System.out.println("moveRed");
}
public static void main(String[] args) throws Exception {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer stk = new StringTokenizer(br.readLine(), " ");
N = Integer.parseInt(stk.nextToken());
K = Integer.parseInt(stk.nextToken());
for(int i=0; i<N; i++) {
stk = new StringTokenizer(br.readLine(), " ");
for(int j=0; j<N; j++) {
map[i][j] = Integer.parseInt(stk.nextToken());
inArr[i][j] = new ArrayList<>(); //init
}
}
for(int i=0; i<K; i++) {
stk = new StringTokenizer(br.readLine(), " ");
int x = Integer.parseInt(stk.nextToken())-1;
int y = Integer.parseInt(stk.nextToken())-1;
int dir = Integer.parseInt(stk.nextToken())-1;
horse[i] = new Pair(x,y,dir, i); //초기엔 동일좌표 없음
inArr[x][y].add(new Pair(x,y,dir,i));
}
//run
boolean success = false;
while(true) {
if(success) break;
if(result > 1000) {
result = -1;
break;
}
for(int i=0; i<K; i++) { // 1~K번말 "순서대로" 이동
Pair p = horse[i]; // 좌표찾기
int nx = p.x+dx[p.dir];
int ny = p.y+dy[p.dir];
// 범위체크 먼저 + 파란색
if(nx<0||ny<0||nx>=N||ny>=N || map[nx][ny] == 2) {
// 이동방향 반대 기록 후 "파란색 아니면" 이동까지
p.dir = redir[p.dir];
nx = p.x+dx[p.dir];
ny = p.y+dy[p.dir];
for(Pair h : inArr[p.x][p.y]) {
if(h.num == p.num) // 현재 말만 선택 (여기선 나머지 쌓인말은 그대로)
h.dir = p.dir; // 방향 기록 -> 디버깅 잘 보기 위해 추가
}
//debug
// for(int j=0; j<N; j++) {
// System.out.println(Arrays.toString(inArr[j]));
// }
// System.out.println("moveBlue");
if(nx<0||ny<0||nx>=N||ny>=N || map[nx][ny] == 2) continue;
else {
// "빨간, 하얀" 로직 재사용
if(map[nx][ny]==0) moveWhite(nx,ny,i);
else if(map[nx][ny]==1) moveRed(nx,ny,i);
}
}
// 하얀색
else if(map[nx][ny] == 0) {
moveWhite(nx,ny,i); // 순번도 넘겨주자
}
// 빨간색
else if(map[nx][ny] == 1) {
moveRed(nx,ny,i);
}
if(inArr[nx][ny].size() >=4) {
success = true;
break;
}
}
result++;
//debug
// System.out.println(result+" 턴 종료");
}
//output
System.out.println(result);
}
static class Pair {
int x; int y; int dir; int num;
public Pair (int x, int y, int dir, int num) {
this.x=x; this.y=y; this.dir=dir; this.num = num;
}
@Override
public String toString() {
// return "Pair [x=" + x + ", y=" + y + ", dir=" + dir + ", num=" + num + "]";
return "Pair [dir=" + dir + ", num=" + num + "]";
}
}
느낀점
생략
댓글남기기