문제 링크
주의사항
- JAVA를 사용하여 프로그램을 사용하였습니다.
- 백준에서 코드를 작성하였을 때 아래 형태에서 Main에서 결과가 출력되어야 합니다.
public class Main{
public static void main(String[] args){
}
}
문제 설명
접근 방법
이 문제에 핵심
1. 한 번의 턴에 1~K번의 말이 차례대로 이동합니다.
2. 이동하려는 칸에 색에 따라 말의 상태를 변경해줍니다.
3. 한 칸에 말이 4개 이상있을 때까지 진행됩니다.
4. 1000턴이 넘어갈 경우 -1을 결과로 출력합니다.
5.1000턴 이전에 한 칸에 4개 이상의 말이 존재하는 최소 턴을 결과로 출력합니다.
한 번의 턴마다 각 말들을 방향대로 이동하는 시뮬레이션이 되도록 구현하였습니다.
※해당 칸에 첫 번째 말만 이동이 가능합니다.
이동하려는 칸에 색에 따라 말의 상태가 변경됩니다.
흰색(0)
해당 칸으로 말을 이동, 이미 칸에 말이 있을 경우 해당 말 위에 순서대로 쌓인다.
빨간색(1)
해당 칸으로 말을 이동, 이미 칸에 말이 있는 경우 해당 말 위에 역순으로 쌓인다.
파란색(2) | 체스판에 벗어날 경우
해당 말 방향을 반대로 바꾸고 이동, 반대로 바꾸고 이동할 칸도 파란색이나 벗어난 경우일 때는 이동X
체스판에 말이 쌓일 수 있으므로 ArrayList<>형태의 배열로 만들었습니다.
문제에서는 예제입력 1이 진행되는 과정을 참고하시면서 제 코드를 살펴보시면 이해가 잘 될 것입니다.
- BufferedReader를 사용하여 입력 값을 받았습니다.
- StringTokenizer을 이용하여 체스판과 말에 대한 정보를 저장하였습니다.
- 게임을 진행하여 말이 4개 쌓이는 최소 턴을 구하는 gameStart함수를 실행하였습니다.
- 말이 4개 쌓이지 못하면 -1, 쌓이면 최소 턴을 BufferedWriter에 저장합니다.
- BufferedWriter에 저장된 결과값을 출력하였습니다.
- gameStart는 각 턴마다 각 말들을 이동하도록 시뮬레이션을 진행하는 함수입니다.
- outBoard는 이동하려는 칸이 체스판에 벗어나는지 확인하는 함수입니다.
- redMove는 이동하려는 칸이 빨간 칸일 때 해당 칸에 역순으로 말이 쌓이는 함수입니다.
- whiteMove는 이동하려는 칸이 하얀 칸일 때 해당 칸에 차례대로 말이 쌓이는 함수입니다.
- directionChange는 파란칸에 만났을 때 방향을 반대로 바꾸는 함수입니다.
import java.util.*;
import java.io.*;
public class Main {
//말 관련 정보 클래스
static class pieces{
int x, y, direction;
public pieces(int x, int y, int direction) {
this.x = x;
this.y = y;
this.direction = direction;
}
}
static int N,K;
static ArrayList<Integer>[][] board; //체스판에 쌓인 말 정보 저장 배열
static pieces[] chessPieces; //말에 대한 정보 저장 배열
static int[][] chessBoard; //체스판 정보 저장 배열
static int[] dx = {1, -1, 0, 0}; //좌우상하 x값 변경
static int[] dy = {0, 0, -1, 1}; //좌우상하 y값 변경
static public void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
//입력값 처리하는 BufferedReader
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
//결과값 출력하는 BufferedWriter
StringTokenizer st = new StringTokenizer(br.readLine()," ");
N = Integer.parseInt(st.nextToken());
K = Integer.parseInt(st.nextToken());
board = new ArrayList[N][N];
chessBoard = new int[N][N];
chessPieces = new pieces[K];
//입력된 체스판 정보 저장
for(int i=0;i<N;i++){
st = new StringTokenizer(br.readLine(), " ");
for(int j=0;j<N;j++)
chessBoard[i][j] = Integer.parseInt(st.nextToken());
}
for(int i=0;i<N;i++){
for(int j=0;j<N;j++)
board[i][j] = new ArrayList();
}
//말에 대한 정보 저장
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 direction = Integer.parseInt(st.nextToken());
chessPieces[i] = new pieces(x,y,direction-1);
board[y][x].add(i);
}
int result = gameStart(); //게임 시작 함수 실행
bw.write(result + "\n"); //턴 BufferedWriter 저장
bw.flush(); //결과 출력
bw.close();
br.close();
}
//게임을 진행하는 함수
static int gameStart(){
int turn = 0;
while(true){
turn++;
if(turn>1000) //턴이 1000을 넘어갔을 때
return -1;
for(int i=0;i<K;i++){
int x = chessPieces[i].x;
int y = chessPieces[i].y;
int direction = chessPieces[i].direction;
if(board[y][x].get(0) != i) //해당 칸 첫 번째 말이 아닌 경우 이동 X
continue;
//해당 방향으로 이동
int tempX = x + dx[direction];
int tempY = y + dy[direction];
if(outBoard(tempX,tempY) || chessBoard[tempY][tempX]==2){//파란 칸일 때
int tempDirection = directionChange(direction); //방향 바꾸기
chessPieces[i].direction = tempDirection;
//방향 바꾸고 한 칸 이동해보기
tempX = x + dx[tempDirection];
tempY = y + dy[tempDirection];
//이동한 칸이 파란색일 때, 이동 X
if(outBoard(tempX,tempY) || chessBoard[tempY][tempX]==2){
continue;
}else if(chessBoard[tempY][tempX] == 1){ //이동한 칸이 빨간 칸일 때
redMove(x,y,tempX,tempY);
}else //이동한 칸이 흰 칸일 때
whiteMove(x,y,tempX,tempY);
}else if(chessBoard[tempY][tempX] == 1){ //빨간칸일 때
redMove(x,y,tempX,tempY);
}else{ //하얀칸일 때
whiteMove(x,y,tempX,tempY);
}
if(board[tempY][tempX].size() >= 4) //이동한 칸에 말이 4개 이상 쌓일 때
return turn; //현재 턴 반환
}
}
}
//체스판에 벗어나는지 확인하는 함수
static boolean outBoard(int x, int y){
return x < 0 || y < 0 || x >= N || y >= N;
}
//이동하려는 칸이 빨간색일 때 역순으로 해당 칸에 말을 쌓는 함수
static void redMove(int x, int y, int tempX, int tempY){
for(int i=board[y][x].size()-1;i>=0;i--){
int temp = board[y][x].get(i);
board[tempY][tempX].add(temp);
chessPieces[temp].x = tempX;
chessPieces[temp].y = tempY;
}
board[y][x].clear();
}
//이동하려는 칸이 하얀색일 때 해당 칸에 말을 쌓는 함수
static void whiteMove(int x, int y, int tempX, int tempY){
for(int i=0;i<board[y][x].size();i++){
int temp = board[y][x].get(i);
board[tempY][tempX].add(temp);
chessPieces[temp].x = tempX;
chessPieces[temp].y = tempY;
}
board[y][x].clear();
}
//말의 방향 반대로 바꾸는 함수
static int directionChange(int direction){
if(direction==0) //좌
return 1;
else if(direction==1) //우
return 0;
else if(direction==2) //상
return 3;
else //하
return 2;
}
}
'백준' 카테고리의 다른 글
[백준, JAVA]18500번, 미네랄 2 (0) | 2022.07.05 |
---|---|
[백준] code.plus(BFS 알고리즘,JAVA)1963번, 소수 경로 (0) | 2022.07.04 |
[백준] code.plus(BFS 알고리즘,JAVA)6087번, 레이저 통신 (0) | 2022.07.02 |
[백준, JAVA]10021번, Watering the Fields (0) | 2022.07.02 |
[백준] code.plus(BFS 알고리즘,JAVA)16236번, 아기 상어 (0) | 2022.06.30 |
댓글