[출처] : 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
메서드를 두 개로 분리하고, 문제에서 제시된 각각의 조건들을 따로 확인했었다.
8
개 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 체스판 위의 룩배치
[개인저장소] : 깃허브