Java를 사용하는 8 명의 여왕

다음 코드는 훌륭하게 작동하지만 시간이 너무 많이 걸립니다. placeQueens에도 많은 시간이 필요합니다. 프로그램은 5 ~ 10 초가 소요됩니다.

public class EightQueen { public static void startSimulation(){ long startTime = System.currentTimeMillis(); char[] board; // Create an array // Repeat while queens are attacking do { // Generate a board board = getNewBoard(); // Place eight queens placeQueens(board); } while (isAttacking(board)); // Display solution print(board); long endTime = System.currentTimeMillis(); System.out.println(endTime - startTime); } /** placeQueens randomly places eight queens on the board*/ public static void placeQueens(char[] board) { int location; for (int i = 0; i < 8; i++) { do { location = placeQueens(); } while (isOccupied(board[location])); board[location] = "Q"; } } /** placeQueens randomly places one queen on the board */ public static int placeQueens() { return (int)(Math.random() * 64); } /** isAttacking returns true if two queens are attacking each other */ public static boolean isAttacking(char[] board) { return isSameRow(board) || isSameColumn(board) || isSameDiagonal(board); } /** isSameRow returns true if two queens are in the same row */ public static boolean isSameRow(char[] board) { int[] rows = new int[8]; for (int i = 0; i < board.length; i++) { if (isOccupied(board[i])) { rows[getRow(i)]++; } if (rows[getRow(i)] > 1) return true; } return false; } /** isSameColumn returns true if two queens are in the same column */ public static boolean isSameColumn(char[] board) { int[] columns = new int[8]; for (int i = 0; i < board.length; i++) { if (isOccupied(board[i])) { columns[getColumn(i)]++; } if (columns[getColumn(i)] > 1) return true; } return false; } /** isSameDiagonal returns true if two queens are on the same diagonal */ public static boolean isSameDiagonal(char[] board) { for (int i = 0; i < board.length; i++) { if (isOccupied(board[i])) { for (int j = 0; j < board.length; j++) { if (isOccupied(board[j]) && Math.abs(getColumn(j) - getColumn(i)) == Math.abs(getRow(j) - getRow(i)) && j != i) { return true; } } } } return false; } /** isOccupied returns true if the element in x is the char Q */ public static boolean isOccupied(char x) { return x == "Q"; } /** getNewBoard returns a char array filled with blank space */ public static char[] getNewBoard() { char[] board = new char[64]; for (int i = 0; i < board.length; i++) board[i] = " "; return board; } /** print displays the board */ public static void print(char[] board) { for (int i = 0; i < board.length; i++) { System.out.print( "|" + ((getRow(i + 1) == 0) ? board[i] + "|\n" : board[i])); } } /** getRow returns the row number that corresponds to the given index */ public static int getRow(int index) { return index % 8; } /** getColumn returns the column number that corresponds to the given index */ public static int getColumn(int index) { return index / 8; } } 

댓글

  • 검색 방법을 사용할 수 있습니다. 역 추적. 첫 번째 자유 (점유되지 않고 공격받지 않은) 위치를 선택할 때마다 여왕을 하나씩 배치하는 것을 반복하십시오. n 번째 여왕에 대한 자유 위치가 없다면, 뒤로 물러나 여왕을 옮기십시오. ( n -1) 현재 위치에서 다음 자유 위치까지. 자유 위치가 ' 없으면 제거 ( n -1)하고 다시 뒤로 물러납니다. 빈 보드로 돌아갔다면 더 이상 가능한 여왕 배치가 없습니다. ' 뒤로 ' 단계에서 여왕 ( n -1)을 성공적으로 이동 한 경우 배치를 진행합니다. n -번째. 무작위 배치는 너무 영향을 미칩니다.
  • ' main() 함수는 어디에 있습니까?
  • @CiaPan 감사합니다.하지만 더 나은 해결책이 있다고 생각합니다.
  • @TobySpeight는 main()에 클래스를 호출하기 만하면됩니다 !!
  • 당신 ' 클래스를 호출 할 수 없습니다. 클래스의 인스턴스를 생성하거나 정적 메서드를 호출 할 수 있습니다. startSimulation()가 주요 기능이어야합니까? 그렇다면 대신 main()라고 부를 수 있습니다.

Answer

bogosort 가 빠른 정렬 알고리즘이 될 수없는 것처럼. “보드를 버리고 N 개의 새로운 여왕을 무작위로 배치”하는 방법은 5 ~ 10 초보다 빠르지 않습니다.

그럼에도 불구하고 실제로 어느 정도 일관되게 해결책을 찾는다는 사실을 알게되어 기뻤습니다. 그리고 질문 자체도 잘 구성되어 있으므로 대답 할 가치가 있다고 생각합니다.

CiaPan이 이미 코멘트에서 제안한 것처럼 n-queens 문제를 해결하는 훨씬 더 좋은 방법은 역 추적입니다. 이 접근 방식을 사용하는 나의 빠른 테스트 프로그램은 1 밀리 초 (또는 그 이하)에 8- 퀸을 해결합니다. (그리고 50ms 안에 20-queens).

그러나 “reset and randomly place n new queens”접근 방식은 흥미 롭습니다. 따라서 하나의 주요 개선 사항을 추가하여 솔루션입니다.

/** placeQueens randomly places eight queens on the board*/ public static void placeQueens(char[] board) { int location; for (int i = 0; i < 8; i++) { do { location = placeQueens(i); } while (isOccupied(board[location])); board[location] = "Q"; } } /** placeQueens randomly places one queen on the board */ public static int placeQueens(int row) { return row * 8 + (int)(Math.random() * 8); } 

여기서이 작은 변화로 인해 솔루션이 지속적으로 100ms 미만으로 떨어질 때까지 시간이 걸렸습니다. 이유는 O (n³)에서 검색 공간을 줄이기 때문입니다. 이것이 작동하는 이유는 모든 솔루션에서 각 행에 정확히 1 개의 퀸이 있기 때문입니다. 따라서 전체 보드가 아닌 각 행에 대해 무작위로 하나씩 생성합니다.

Comments

  • 훌륭한 답변에 감사하지만 ' 이미 빠른 작업을 마쳤지만 여전히 임의의 여왕 설정에 문제가있는 것 같습니다. .
  • 고려할만한 또 다른 점이 있습니다. @IbrahimAli는 ' 실제로 자신의 목표가 무엇인지 말하지 않았거나 아무 유효한 배열을 찾거나 8 명의 여왕의 모든 유효한 배열. 루프로 묶인 체계적인 검색은 후자를 수행합니다 (retur n 가능한 모든 솔루션, 그리고 각각 정확히 한 번), 무작위 생성은 불가능하지만 (답을 반복 할 수 있으며 모든 가능성을 발견했는지 알 수 없습니다. RNG 품질이 좋지 않으면 일부를 찾을 수 불가능 할 수도 있습니다).
  • @CiaPan I ' iv id = n 부울에 대한 “9a5035c1fb”>

위치 단순히 부울 배열을 만들고 무작위에 의존하여 '의 색인을 사용합니다. 퀸즈, 생성 된 모든 퀸즈는 부울 배열에서 잘못된 인덱스를 false로 설정하여 시간이 짧습니다.

  • @Imus You don ' do – while 루프, for (int i = 0; i < 8; i++) 루프에 의해 호출 된 각 placeQueens(i)는 별도의 행에 위치를 할당합니다. 따라서 충돌은 불가능하고 테스트는 시간 낭비입니다.
  • Aha 진정한 CiaPan. 잘 발견되었습니다. 원래 코드의 각 행에 하나씩 생성하기 위해 최소한의 변경 만 수행했습니다. 그래서 '이 i를 메서드에 전달했습니다. 또한 지금 중복 된 검사를 발견했지만 솔루션을 찾는 데 1 밀리 초 미만의 시간이 소요됩니다. 따라서 ' 어쨌든 차이점을 구분할 수 없습니다.
  • 답글 남기기

    이메일 주소를 발행하지 않을 것입니다. 필수 항목은 *(으)로 표시합니다