문제 설명
https://www.acmicpc.net/problem/23288
- 처음 주사위는 지도 위에 윗면이 1, 아래는 6
- 처음 이동 방향은 동쪽
- 조건
- 점수 계산
문제에 대한 아이디어
이 문제를 해결하기 위해서는 필요한 메소드를 생각해야 할 필요가 있습니다.
- 주사위 움직이는 메소드
- 위치를 움직이는 메소드
- 방향을 정하는 메소드
- 점수를 계산하는 메소드
주사위를 움직이는 메소드
public static void moveDice(int dir) {
if(dir == 1) { // 동쪽
int temp = dice[6];
dice[6] = dice[3];
dice[3] = dice[1];
dice[1] = dice[4];
dice[4] = temp;
}
else if (dir == 2) { // 남쪽
int temp = dice[6];
dice[6] = dice[5];
dice[5] = dice[1];
dice[1] = dice[2];
dice[2] = temp;
}
else if (dir == 3) { //서쪽
int temp = dice[6];
dice[6] = dice[4];
dice[4] = dice[1];
dice[1] = dice[3];
dice[3] = temp;
}
else {
int temp = dice[6];
dice[6] = dice[2];
dice[2] = dice[1];
dice[1] = dice[5];
dice[5] = temp;
}
}
코드를 더 예쁘게 짤 수도 있을 것 같지만 보자마자 생각난 방법은 위의 코드였습니다. 동, 서, 남, 북으로 움직일 때 위의 전개도의 숫자 중 바뀌는 것을 찾아 순서대로 바꾸어 주었습니다.
좌표 변경
public static void move(Pair now, int n , int m) {
if(nowDir == 1) {
if(now.x + 1 <= m){
now.x += 1;
moveDice(1);
}
else {
now.x -= 1;
moveDice(3);
nowDir = 3;
}
}
else if (nowDir == 2) {
if(now.y + 1 <= n){
now.y += 1;
moveDice(2);
}
else {
now.y -= 1;
moveDice(4);
nowDir = 4;
}
}
else if (nowDir == 3) {
if(0 < now.x - 1 ){
now.x -= 1;
moveDice(3);
}
else {
now.x += 1;
moveDice(1);
nowDir = 1;
}
}
else {
if(0 < now.y - 1) {
now.y -= 1;
moveDice(4);
}
else {
now.y += 1;
moveDice(2);
nowDir = 2;
}
}
}
좌표 변경 동안 현재의 방향에서 움직일 때 범위를 벗어나지 않으면 그 방향으로 움직이도록 설정했습니다. 또한 벽을 만나면 반대 방향으로 변경했습니다. 방향을 변경하고 나서는 moveDice를 통해 주사위 또한 변경해 주었습니다. 지금 생각해 보니 숫자를 쓰지 않고 nowDir만 적어도 될 것 같습니다.
방향 설정
public static void checkNext(int board[][], Pair now) {
result += scores[now.y][now.x];
if(board[now.y][now.x] < dice[6]) {
nowDir = (nowDir + 1) % 5;
if(nowDir == 0) nowDir = 1;
}
else if(board[now.y][now.x] > dice[6]) {
nowDir = (nowDir - 1) % 5;
if(nowDir == 0) nowDir = 4;
}
}
점수를 계산하고 다음 방향을 지정해 주었습니다. 조건에 따라 시계방향 90도와 반시계방향 90도를 생각해서 짜주었습니다.
점수 계산
input값을 확인하니 매시간 bfs를 돌아도 되지만 한 번 다 구해 놓고 사용하면 k가 커질 때는 유용하다고 생각했습니다.
public static void score(int board[][], Pair now, int n , int m) {
Deque<Pair> dq = new ArrayDeque<>();
dq.add(now);
visited[now.y][now.x] = true;
int num = board[now.y][now.x];
int size = 0;
ArrayList<Pair> arr = new ArrayList<>();
arr.add(now);
while(!dq.isEmpty()){
Pair temp = dq.removeFirst();
size += 1;
for(int i = 0; i < 4; ++i) {
int ny = temp.y + dy[i];
int nx = temp.x + dx[i];
if(ny < 1 || ny > n || nx < 1 || nx > m) continue;
if(visited[ny][nx]) continue;
visited[ny][nx] = true;
if(board[ny][nx] == num) {
dq.addLast(new Pair(ny,nx));
arr.add(new Pair(ny,nx));
}
}
}
for(int i = 0; i < arr.size(); ++i) {
scores[arr.get(i).y][arr.get(i).x] = num*size;
}
}
제일 처음 반복문을 통해 scores 2차원 배열에 점수를 모두 적어주었습니다. 그 후 그 지점에 점수를 결과값에 더해주었습니다. 이렇게 하면 제일 처음 BFS할 때 빼고은 O(1)시간안에 점수를 더할 수 있습니다.
전체 코드
'코딩테스트 공부 > 알고리즘 공부' 카테고리의 다른 글
백준 17232 생명 게임 (JAVA) (1) | 2024.02.12 |
---|---|
자바에서 정렬에 대해 (1) | 2024.01.04 |
백준 16637 괄호 추가하기 (JAVA) (0) | 2023.10.27 |
등대 (프로그래머스) JAVA (1) | 2023.10.19 |
백준 17298 오큰수 자바 (2) | 2023.10.18 |