[SWEA D3] 15612. 체스판 위의 룩 배치

popolarburr·2023년 4월 23일
0
post-thumbnail

- 문제

[출처] : SWEA D3 체스판 위의 룩배치


- 풀이


import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Arrays;
 
class Solution {
    private static final int BOARD_SIZE = 8;
    private static final int PIECE = 8;
    static String[][] board;
 
 
    static boolean checkCondition() { // 정확히 8개
        int count = 0;
        for (int i = 0; i < BOARD_SIZE; i++) {
            for (int j = 0; j < BOARD_SIZE; j++) {
                if (board[i][j].equals("O")) {
                    if (!checkRowAndColumn(i, j)) {
                        return false;
                    }
                    count++;
                }
            }
        }
        return count == PIECE;
    }
 
    static boolean checkRowAndColumn(int i, int j) {
        for (int x = 0; x < BOARD_SIZE; x++) {
            if (x != i && board[x][j].equals("O")) return false;
        }
 
        for (int y = 0; y < BOARD_SIZE; y++) {
            if (y != j && board[i][y].equals("O")) return false;
        }
        return true;
    }
 
 
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        int T = Integer.parseInt(br.readLine());
 
        for (int tc = 1; tc <= T; tc++) {
            board = new String[BOARD_SIZE][BOARD_SIZE];
 
            for (int i = 0; i < BOARD_SIZE; i++) {
                Arrays.fill(board[i], "");
            } // end of sub for-loop
 
            for (int i = 0; i < BOARD_SIZE; i++) {
                String tmp = br.readLine();
                for (int j = 0; j < BOARD_SIZE; j++) {
                    board[i][j] = String.valueOf(tmp.charAt(j));
                }
            } // end of sub for-loop
 
 
            if (checkCondition()) {
                System.out.printf("#%d yes\n", tc);
            } else {
                System.out.printf("#%d no\n", tc);
            }
 
        } // end of main for-loop
 
    } // end of main method
 
}

- 정리

내가 처음에 풀 때는 checkCondition 메서드를 두 개로 분리하고, 문제에서 제시된 각각의 조건들을 따로 확인했었다.

  • 조건 1: 룩은 무조건 8
  • 조건 2: 룩은 서로 공격 못하고, 이로인해 같은 행 혹은 열에 존재할 수 없다.
 static boolean check1() { // 정확히 8개
        int count = 0;
        for (int i = 0; i < BOARD_SIZE; i++) {
            for (int j = 0; j < BOARD_SIZE; j++) {
                if (board[i][j].equals("O")) {
                    count++;
                }
            }
        }
        return count == PIECE;
    }

    static boolean check2() { // 같은 열에 있거나 행에 X
        for (int i = 0; i < BOARD_SIZE; i++) {
            int rowCheck = 0;
            for (int j = 0; j < BOARD_SIZE; j++) { // 행 검사
                if (rowCheck > 1) {
                    return false;
                }
                if (board[i][j].equals("O")) {
                    rowCheck++;
                }
            }

            int columnCheck = 0;
            for (int j = 0; j < BOARD_SIZE; j++) { // 열검사
                if (columnCheck > 1) {
                    return false;
                }
                if (board[j][i].equals("O")) {
                    columnCheck++;
                }
            }
        }
        return true;
    }
    
    
    ...
    
    
    public static void main(String[] args) {
    
    	...
        if (check1() && check2()) {
                System.out.printf("#%d yes\n", tc);
            } else {
                System.out.printf("#%d no\n", tc);
		}

    }

내가 처음에 푼 방식은 이러하다. 마지막에 올바른 체스판인지 확인하기 위해 check1() check2()를 각각 비교했었다. 이렇게 풀면 하나의 맹점이 존재하는데, 바로 각각의 상태를 비교못한다는 것이다

어떤 의미냐? check1()만 보면 체스판(8X8)에 "O"가 8개인지만 체크하고 있다. 이렇게 되면 한 줄에 8개가 있고, 나머지 어디에도 없다고 해도 true가 리턴된다. check1()true인 상태에서 check2()를 들어가게 되면,당연히 false가 리턴된다.

운좋게 문제에서 제시된 테스트케이스상에서는 통과를 했었다. 그렇게 기쁜마음에 곧장 제출했고, 왜 틀렸는지 전혀 감을 못잡고 있었다. 그러다 계속 꼼꼼하게 보다 보니 조건의 상태를 둘 다 동시에 비교해야 한다는 것을 깨달았고, 수정한 후에 문제에 통과하였다.

통과한 코드는 풀이에 있는 코드인데, 어떤 방식이냐면 체스판에는 8개의 룩이 존재해야한다. 그렇기에 룩이 발견된다면 해당 좌표(i, y)checkRowAndColumn()메서드에전달한다. 이 좌표를 통해 하나는 행을, 하나는 열을 비교한다.
그래서 각각 for문을 하나는 i = 행을 고정하고, 하나는 y = 열을 고정하여 체스판에 맞춰 돌린다음 거기 마저 통과하면 count를 ++한다. 그렇게 룩이 서로 공격못한다는 조건을 통과했으면, 마지막에 count(체스판 전체에서의 룩의 개수)를 상수값으로 정해놓은 값과 비교하여 boolean타입으로 출력한다.

거기서 true면 해당 케이스 yes, false면 해당 케이스 no로 프로그램을 종료한다.

늘 그렇지만 꼼꼼히 읽고, 제한조건을 끝까지 이해하고 틀린건 없는지 끝까지 의심해봐야할 것이다.


[출처] : SWEA D3 체스판 위의 룩배치
[개인저장소] : 깃허브

profile
차곡차곡

0개의 댓글