17780 새로운 게임 : https://www.acmicpc.net/problem/17780
주어진 조건
말의 정보(y,x,번호,방향)를 담는 Unit클래스를 만든 후 List< Unit >[][] unitBoard = new List[N][N]
를 생성한다.
unitBoard배열을 통해 unitBoard[i][j]에 존재하는 말의 리스트를 알수있다.
이때 unitBoard[i][j] 리스트에 첫번째 Unit이 가장 아래있는 말이다.
풀이 순서는 아래와 같다.
1. 풀이에 필요한 변수 및 배열을 초기화한다.
2. turn이 1000이하일때까지 반복한다.
3.1번 말 부터 K번 말까지 이동시킨다.
reverse
해서 추가한다.public class 새로운게임 {
static int N;
static int K;
static int[][] board;
static List<Unit>[][] unitBoard;
static Unit[] units;
static int[] dy = {-1, 0, 1, 0};
static int[] dx = {0, 1, 0, -1};
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
StringTokenizer st = new StringTokenizer(br.readLine(), " ");
N = Integer.parseInt(st.nextToken());
K = Integer.parseInt(st.nextToken());
//타일 색 배열
board = new int[N][N];
//Unit 저장 배열
units = new Unit[K + 1];
//Unit List 배열
unitBoard = new List[N][N];
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
unitBoard[i][j] = new ArrayList<>();
}
}
for (int i = 0; i < N; i++) {
st = new StringTokenizer(br.readLine(), " ");
for (int j = 0; j < N; j++) {
board[i][j] = Integer.parseInt(st.nextToken());
}
}
for (int i = 0; i < K; i++) {
st = new StringTokenizer(br.readLine(), " ");
int y = Integer.parseInt(st.nextToken()) - 1;
int x = Integer.parseInt(st.nextToken()) - 1;
int d = Integer.parseInt(st.nextToken());
//방향 변경을 위한 방향 변경
// 0 : ↑, 1 : →, 2 : ↓, 3 : ←
if (d == 2) {
d = 3;
} else if (d == 3) {
d = 0;
} else if (d == 4) {
d = 2;
}
Unit unit = new Unit(i + 1, y, x, d);
unitBoard[y][x].add(unit);
units[i + 1] = unit;
}
int answer = -1;
for (int turn = 1; turn <= 1000; turn++) {
if (start()) {
answer = turn;
break;
}
}
bw.write(String.valueOf(answer));
bw.flush();
bw.close();
}
static boolean start() {
//해당 턴에서 1번말 부터 K번 말까지 순서대로 이동
for (int u = 1; u <= K; u++) {
Unit current = units[u];
int currentY = current.y;
int currentX = current.x;
//해당 말이 가장 아래에 있지않으면 제외
if (unitBoard[currentY][currentX].get(0).num != current.num)
continue;
int ny = currentY + dy[current.d];
int nx = currentX + dx[current.d];
//이동할 좌표가 파란색 또는 범위 밖이라면 방향을 반대로 변경한다.
if (ny < 0 || nx < 0 || ny >= N || nx >= N || board[ny][nx] == 2) {
int nd = (current.d + 2) % 4;
ny = currentY + dy[nd];
nx = currentX + dx[nd];
current.d = nd;
//변경한 방향으로 이동해도 파란색이거나 범위 밖이라면 방향만 바뀐채로 다음 말 이동
//변경한 방향이 흰색이거나 빨간색이면 다음 코드 실행
if (ny < 0 || nx < 0 || ny >= N || nx >= N || board[ny][nx] == 2) {
continue;
}
}
//이동할 좌표가 빨간색
if (board[ny][nx] == 1) {
int size = unitBoard[currentY][currentX].size();
//현재 좌표의 말들을 반대로 이동할 좌표의 list에 추가
for (int i = size-1; i >= 0; i--) {
Unit unit = unitBoard[currentY][currentX].get(i);
unit.y = ny;
unit.x = nx;
unitBoard[ny][nx].add(unit);
}
unitBoard[currentY][currentX].clear();
}
//이동할 좌표가 흰색
else {
int size = unitBoard[currentY][currentX].size();
//현재 좌표의 말들을 이동할 좌표의 list에 추가
for (int i = 0; i < size; i++) {
Unit unit = unitBoard[currentY][currentX].get(i);
unit.y = ny;
unit.x = nx;
unitBoard[ny][nx].add(unit);
}
unitBoard[currentY][currentX].clear();
}
//말을 이동시켰을때 이동시킨 좌표에 말이 4개 이상 겹쳐져있다면 함수 종료
if(unitBoard[ny][nx].size()>=4) return true;
}
return false;
}
static class Unit {
int num;
int y;
int x;
int d;
public Unit(int num, int y, int x, int d) {
this.num = num;
this.y = y;
this.x = x;
this.d = d;
}
}
}