본문 바로가기

Algorithm/Practice

이코테 - 청소년 상어 with JAVA

 

 

이 문제는 로직은 간단하다. 데이터의 수가 적고 범위가 한정적이라 완전탐색으로 가능하다.

하지만 조건이 많아 실수가 발생해서 기록을 해두려고 한다.

 

 

세가지를 주의하자.

  • 문제의 조건을 분리해두자.
  • 설계를 하고 코딩을 하자.
  • int[][] 는 복사시 반복문을 통해 항상 따로 해주자.

 

 

 

코드


import java.util.*;

// 청소년 상어
public class Q2 {
    public static int[][] size_map = new int[4][4];
    public static int[][] dir_map= new int[4][4];
    public static List<Integer> fish_size = new ArrayList<>();
    // 상어 정보
    public static int[] pos = {0, 0};
    public static int dir;
    public static int result = 0;
    public static int answer = 0;
    // 반시계 방향 (위에서부터 시작)
    public static int[] dx = {-1, -1, 0, 1, 1, 1, 0, -1};
    public static int[] dy = {0, -1, -1, -1, 0, 1, 1, 1};
    public static void main(String[] args){
        Scanner sc = new Scanner(System.in);
        for(int i=0; i<4; i++){
            for(int j=0; j<4; j++){
                size_map[i][j] = sc.nextInt();
                dir_map[i][j] = sc.nextInt()-1;
                fish_size.add(size_map[i][j]);
            }
        }

        // 배경
        // 상하좌우, 대각선 이동
        // 상어는 (0, 0) 먹고 시작
        result += size_map[0][0];
        answer += size_map[0][0];
        size_map[0][0] = 0;
        dir = dir_map[0][0];
        dir_map[0][0] = 0;


        // 물고기 정렬
        Collections.sort(fish_size);


        // 이동 로직

        // 물고기 이동
        fish_move();
        // 상어 이동
        shark_move();
        System.out.println(answer);
    }

    // 상어 이동
    // 지정된 방향으로만 이동가능, 한번에 여러칸 이동 가능
    // 물고기가 있는 칸 이동시 물고기 먹고, 그 물고기가 가진 방향 가짐
    // 이동하는 중 지나는 물고기는 먹지 않는다.
    // 이동할 수 있는 칸이 없다면 종료
    public static void shark_move(){
        // 상어 이동
        List<List<Integer>> fishes = new ArrayList<>();
        int next_x = pos[0];
        int next_y = pos[1];
        while(true) {
            next_x += dx[dir];
            next_y += dy[dir];
            if (next_x < 0 | next_x >= 4 | next_y < 0 | next_y >= 4) {
                break;
            }
            // 물고기 없는 칸으로는 이동 불가능
            if (size_map[next_x][next_y] == 0) {
                continue;
            }
            fishes.add(Arrays.asList(next_x, next_y));
        }
        if(fishes.size() == 0){
            return;
        }
        for(List<Integer> fish : fishes){
            // 기존 정보 추출
            int fish_x = fish.get(0);
            int fish_y = fish.get(1);
            int fish_size = size_map[fish_x][fish_y];
            int fish_dir = dir_map[fish_x][fish_y];

            int shark_x = pos[0];
            int shark_y = pos[1];
            int shart_dir = dir;

            int[][] new_size_map = new int[4][4];
            int[][] new_dir_map = new int[4][4];
            for(int i=0; i<4; i++){
                for(int j=0; j<4; j++){
                    new_size_map[i][j] = size_map[i][j];
                    new_dir_map[i][j] = dir_map[i][j];
                }
            }

            // 먹음
            result += fish_size;
            size_map[fish_x][fish_y] = 0;
            dir_map[fish_x][fish_y] = 0;
            pos[0] = fish_x;
            pos[1] = fish_y;
            dir = fish_dir;

            // 결과 갱신
            answer = Math.max(answer, result);


            // 다시 이동
            fish_move();
            shark_move();

            // 물고기 되돌리기
            for(int i=0; i<4; i++){
                for(int j=0; j<4; j++){
                    size_map[i][j] = new_size_map[i][j];
                    dir_map[i][j] = new_dir_map[i][j];
                }
            }

            // 뱉음
            result -= fish_size;
            size_map[fish_x][fish_y] = fish_size;
            dir_map[fish_x][fish_y] = fish_dir;
            pos[0] = shark_x;
            pos[1] = shark_y;
            dir = shart_dir;
        }
    }


    // 물고기 이동
    // 번호가 작은 물고기부터 이동
    // 한칸만 이동 가능
    // 이동할 수 있는 칸 : 빈칸, 다른 물고기가 있는 칸
    // 이동할 수 없는 칸 : 상어 존재, 공간의 경계를 넘는 칸
    // 이동 방식 : 현재 방향부터 시작해 45도 회전해가며 이동, 이동 못하면 그대로 위치
    // 다른 물고기 있는 칸 이동시 위치 바꾼다.
    public static void fish_move(){
        // 작은 물고기부터 이동
        for(int fish : fish_size){
            for(int i=0; i<4; i++){
                // 이미 처리한 물고기 재처리 방지
                boolean conti = true;
                for(int j=0; j<4; j++){
                    if(size_map[i][j] == fish){
                        // 회전
                        int dir = dir_map[i][j];
                        for(int d=0; d<8; d++){
                            // 이동할 칸
                            int next_x = i + dx[dir];
                            int next_y = j + dy[dir];
                            // 범위 벗어나면 진행
                            if(next_x < 0 | next_x >= 4 | next_y < 0 | next_y >= 4){
                                dir += 1;
                                if(dir == 8){
                                    dir = 0;
                                }
                                continue;
                            }
                            // 상어 존재하는 칸
                            if(next_x == pos[0] && next_y == pos[1]){
                                dir += 1;
                                if(dir == 8){
                                    dir = 0;
                                }
                                continue;
                            }
                            // 빈칸
                            if(size_map[next_x][next_y] == 0){
                                size_map[next_x][next_y] = size_map[i][j];
                                size_map[i][j] = 0;
                                dir_map[next_x][next_y] = dir;
                                dir_map[i][j] = 0;
                                break;
                            }
                            // 다른 물고기 있는 칸
                            else{
                                size_map[i][j] = size_map[next_x][next_y];
                                size_map[next_x][next_y] = fish;
                                dir_map[i][j] = dir_map[next_x][next_y];
                                dir_map[next_x][next_y] = dir;
                                break;
                            }
                        }
                        conti = false;
                        break;
                    }
                }
                if(!conti){
                    break;
                }
            }
        }
    }
}

'Algorithm > Practice' 카테고리의 다른 글

백준 - 비슷한 단어 with JAVA  (0) 2023.11.10
백준 - 내리막길  (1) 2023.11.02
이코테 - 최종 순위 with JAVA  (0) 2023.10.08
이코테 - 행성 터널 with JAVA  (1) 2023.10.05
이코테 - 탑승구 with JAVA  (0) 2023.10.04