티스토리 뷰


백준 #1986 체스

 

1986번: 체스

첫째 줄에는 체스 판의 크기 n과 m이 주어진다. (1 ≤ n, m ≤ 1000) 그리고 둘째 줄에는 Queen의 개수와 그 개수만큼의 Queen의 위치가 입력된다. 그리고 마찬가지로 셋째 줄에는 Knight의 개수와 위치,

www.acmicpc.net

🔒 문제 설명

n×m 크기의 체스 판과, 상대팀의 Queen, Knight, Pawn의 위치가 주어져 있을 때, 안전한 칸이 몇 칸인지 세는 프로그램을 작성하시오. (안전한 칸이란 말은 그곳에 자신의 말이 있어도 잡힐 가능성이 없다는 것이다.)

참고로 Queen은 가로, 세로, 대각선으로 갈 수 있는 만큼 최대한 많이 이동을 할 수 있는데 만약 그 중간에 장애물이 있다면 이동을 할 수 없다. 그리고 Knight는 2 ×3 직사각형을 그렸을 때, 반대쪽 꼭짓점으로 이동을 할 수 있다. 아래 그림과 같은 8칸이 이에 해당한다.

이때 Knight는 중간에 장애물이 있더라도 이동을 할 수 있다. 그리고 Pawn은 상대팀의 말은 잡을 수 없다고 하자(즉, 장애물의 역할만 한다는 것이다).

예를 들어 다음과 같이 말이 배치가 되어 있다면 진하게 표시된 부분이 안전한 칸이 될 것이다. (K : Knight, Q : Queen, P : Pawn)

⌨️ 입력

첫째 줄에는 체스 판의 크기 n과 m이 주어진다. (1 ≤ n, m ≤ 1000) 그리고 둘째 줄에는 Queen의 개수와 그 개수만큼의 Queen의 위치가 입력된다. 그리고 마찬가지로 셋째 줄에는 Knight의 개수와 위치, 넷째 줄에는 Pawn의 개수와 위치가 입력된다. 즉 둘째 줄, 셋째 줄, 넷째 줄은  k, r1, c1, r2, c2,..., rk, ck 이 빈칸을 사이에 두고 주어진다는 것이다. 여기서 ri는 i번째 말의 행 위치, ci는 i번째 말의 열 위치를 의미한다. 한 칸에는 하나의 말만 놓인다고 가정한다. Knight, Queen, Pawn의 개수는 각각 100을 넘지 않는 음이 아닌 정수이다.

🖥️ 출력

첫째 줄에 n×m 체스판에 안전한 칸이 몇 칸인지 출력하시오.

 


 ♟️오답 기록

얼마 전부터 재미를 붙인 체스가 코딩 문제 중에 있어서 신나서 클릭해서 도전해 봤는데 고려할 케이스가 너무 많아서 골치 아팠다. 그래도 포기하지 않고 열심히 구현했는데... '틀렸습니다'.. 다음에 꼭 다시 시도하고자 해당 오답 코드를 기록한다.

 

우선 폰의 위치에 따라 퀸의 이동 경로가 달라지기 때문에 처음 퀸의 좌표를 입력받자마자 보드에 이동 경로를 표시해서는 안된다. 그러므로 일단 ArrayList에 퀸의 좌표를 저장한다.

 

두 번째 나이트의 경우에는 장애물이 있어도 뛰어넘을 수 있으므로 입력받자마자 바로 이동 경로를 표시한다. 나이트 본인의 위치에는 '2', 이동할 수 있는 위치에는 '1'을 저장했다. 

 

폰의 경우 장애물의 역할만 하고 움직일 수 없으므로 본인의 위치에만 '2'를 표시한다.

 

이제 모든 말이 올라왔으니 퀸이 움직일 차례다. 퀸은 총 8가지 방향으로 움직일 수 있다. 각 경우마다 while문 안에 if문을 사용해서 코드를 구현했는데 (1) 현재 좌표가 보드의 범위를 벗어나거나 (2) 현재 위치에 다른 말이 있을 때 break 한다. 여기서 오랜만에 조건문에 대해 복습했다. 바로 "조건문에서 | 와 ||의 차이" 

 

조건문에서 '|'와 '||'의 차이 혹은 '&'와 '&&'의 차이

 

✅ '|' 하나 사용한 경우

if( 조건 1 | 조건 2 )

조건 1이 True여도 조건 2가 True인지 False인지 검사한다.

 

✅'||' 두 개 사용한 경우

if( 조건 1 || 조건 2 )

조건 1이 True -> 조건 2는 검사하지 않는다. -> 조건 2 안 봐도 조건문 자체가 True로 판명남

조건 1이 False -> 조건 2를 검사한다.

 

마찬가지로 && 연산자일 경우 

 

✅ '&' 하나 사용한 경우

if( 조건 1 & 조건 2 )

조건 1이 False여도 조건 2가 True인지 False인지 검사한다.

 

✅'&&' 두 개 사용한 경우

if( 조건 1 && 조건 2 )

조건 1이 False -> 조건 2는 검사하지 않는다. -> 조건 2 안 봐도 조건문 자체가 이미 False로 판명 남

조건 1이 True -> 조건 2를 검사한다.

 

 

우선 위에서 (2) 번 조건을 작성할 때, board(i)(j)==2 이런 식으로 조건이 작성되는데 만약 i, j 둘 중 하나라도 인덱스 범위를 벗어났다면 바로 Index Out Of Range 에러가 발생할 것이다. 이때, if문에 '||'로 인덱스 체크 조건을 앞에 함께 써주면 인덱스 범위에 해당하는 것에 한해서 board 접근을 할 것이다. 

 

 

 

🔎 나의 코드 (오답)

import java.util.*;

public class Main {
    public static void main(String[] args) throws Exception {
        Scanner in = new Scanner(System.in);

        // 체스판 가로 세로
        int n = in.nextInt();
        int m = in.nextInt();

        int[][] board = new int[n][m];

        // Queen 좌표 입력
        int q= in.nextInt();
        ArrayList<ArrayList<Integer>> queen = new ArrayList<>();

        for(int i = 0; i < q; i++){
            ArrayList<Integer> location = new ArrayList<>();
            int x = in.nextInt()-1;
            int y = in.nextInt()-1;

            location.add(x);
            location.add(y);
            queen.add(location);

            board[x][y]=2;
        }


        // Knight 좌표 입력 / 보드에 나이트 위험 구역 표시
        int k= in.nextInt();

        for(int i = 0; i < k; i++){
            int x = in.nextInt()-1;
            int y = in.nextInt()-1;

            board[x][y]=2;

            if(x-1>-1 && y-2>-1) board[x-1][y-2]=1;
            if(x-2>-1 && y-1>-1) board[x-2][y-1]=1;
            if(x-2>-1 && y+1<m) board[x-2][y+1]=1;
            if(x-1>-1 && y+2<m) board[x-1][y+2]=1;
            if(x+1<n && y+2<m) board[x+1][y+2]=1;
            if(x+2<n && y+1<m) board[x+2][y+1]=1;
            if(x+2<n && y-1>-1) board[x+2][y-1]=1;
            if(x+1<n && y-2>-1) board[x+1][y-2]=1;
        }

        // Pawn 좌표 입력 / pawn 위치 표시
        int p= in.nextInt();
        for(int i = 0; i < p; i++){
            int x = in.nextInt()-1;
            int y = in.nextInt()-1;

            board[x][y] = 2;
        }


        for(int i = 0; i < q; i++){
            int x = queen.get(i).get(0);
            int y = queen.get(i).get(1);

            //[1] 12시 방향 탐색
            int tmp = x;
            while(true){
                tmp--;
                if(tmp == -1 || board[tmp][y] == 2) break;
                else board[tmp][y] = 1;
            }

            //[2] 6시 방향 탐색
            tmp = x;
            while(true){
                tmp++;
                if(tmp == n || board[tmp][y] == 2) break;
                else board[tmp][y] = 1;
            }

            //[3] 3시 방향 탐색
            tmp = y;
            while(true){
                tmp++;
                if(tmp == m || board[x][tmp] == 2) break;
                else board[x][tmp] = 1;
            }

            //[4] 9시 방향 탐색
            tmp = y;
            while(true){
                tmp--;
                if(tmp == -1 || board[x][tmp] == 2) break;
                else board[x][tmp] = 1;
            }

            //[5] 1~2시 방향 대각선 탐색
            int tmpx = x;
            int tmpy = y;
            while(true){
                tmpx--;
                tmpy++;
                if(tmpx == -1 || tmpy ==m || board[tmpx][tmpy] == 2) break;
                else board[tmpx][tmpy] = 1;
            }

            //[6] 4~5시 방향 대각선 탐색
            tmpx = x;
            tmpy = y;
            while(true){
                tmpx++;
                tmpy++;
                if(tmpx == n || tmpy ==m || board[tmpx][tmpy] == 2) break;
                else board[tmpx][tmpy] = 1;
            }

            //[7] 7~8시 방향 대각선 탐색
            tmpx = x;
            tmpy = y;
            while(true){
                tmpx++;
                tmpy--;
                if(tmpx == n || tmpy == -1 || board[tmpx][tmpy] == 2) break;
                else board[tmpx][tmpy] = 1;
            }

            //[8] 10~11시 방향 대각선 탐색
            tmpx = x;
            tmpy = y;
            while(true){
                tmpx--;
                tmpy--;
                if(tmpx == -1 || tmpy == -1 || board[tmpx][tmpy] == 2) break;
                else board[tmpx][tmpy] = 1;
            }

        }


        int safe_zone = 0;
        //보드판 출력
        for(int i = 0; i<n; i++){
            for(int j = 0; j<m; j++){
                if(board[i][j]==0) safe_zone++;
                ////
                System.out.print(board[i][j]+" ");
            }
            ////
            System.out.println();
        }
        System.out.println("safe: "+safe_zone);
    }
}

 

공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
TAG
more
«   2024/09   »
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30
글 보관함