1. 문제에 대한 이해
- 우리가 풀어야 할 문제는 무엇인가?
- 주어진 자료는 무엇인가?
- 조건은 무엇인가?
- 우리가 문제를 풀기 위해 주어진 자료가 충분한가?
- 숨겨진 조건이나 자료가 있는가? 그렇다면 그 것을 다른 방법으로 해석해보라.
- 문제는 무엇인가?
-> 어떻게 N-queen 문제를 풀 것인가?
-> N-queen 문제란 무엇인가?
-> 어떻게 N-queen을 놓을 수 있는가?
-> N-queen을 놓는다는 것이 무엇인가?
-> 어떻게 놓는가?
-> 놓는다는 것이 무엇인가?
-> 문제가 무엇인가?
-> 무슨 문제가 발생하는가?
-> 특정 행에서 선택하게 하면 어떠한가?
-> 어떻게 선택하게 하는가?
-> 그리고 중복되지 않게 선택하게 하려면 어떻게 하는가?
-> 퀸은 대각선으로 움직일 수 있다.
-> 대각선으로 움직일 수 있다는 것이 무엇인가?
-> 어떻게 true 처리를 하는가?
-> true처리를 한다는 것이 무엇인가?
-> 한 row에서 무조건 하나를 선택해야 하는가?
-> 이것을 어떻게 하는가?
-> 이것을 한다는 것이 무엇인가?
-> 어떻게 검사를 해야 하는가?
-> i는 무엇인가?
-> 생각을 한다
-> 여기서 또 검사를 한다
-> 무엇을 검사해야 하는가?
-> 여기서 다르게 검사를 해야 한다
-> 어떻게 검사를 하는가?
-> 어떻게 대각선을 검사하는가?
-> 문제가 무엇인가?
-> 왜 검사가 제대로 안되는가?
-> 검사가 제대로 안된다는 것이 무엇인가?
-> 왜 이걸 못 걸러내는가?
-> 못 걸러낸다는 것이 무엇인가?
-> true, false 처리가 잘못되었다.
-> 무엇이 잘못되었는가?
-> 그때 바꿨던 점에 대해서만 해야 한다
-> 그 때 바꿨던 점에 대해서만 한다는 것이 무엇인가?
-> 그것을 어떻게 구분하는가?
-> 구분한다는 것이 무엇인가?
-> 그 리스트를 갖고 있어야 한다
-> 어떻게 갖고 있는가?
->
2. 계획
- 전에 비슷한 문제를 알고 있는가?
- 이 문제를 푸는데 있어서 유용하게 쓸 수 있는 지식은 무엇인가?
- 비슷한 문제를 풀어본 적이 있다면 그 것을 활용할 수 있는가?
- 만약 문제를 풀 수 없다면 문제를 더 단순하게 하기 위해서 주어진 조건을 버려보아라
- 주어진 자료로부터 유용한 것을 이끌어 낼 수 있는가?
- 자료는 모두 사용했는가?
- 조건을 모두 사용했는가?
- 문제에 포함된 핵심적인 개념은 모두 고려했는가?
3. 실행
- 풀이 계획을 실행하고, 각 단계가 올바른지 점검하라.
[내 풀이]
import java.util.*;
class Pair{
int x;
int y;
public Pair(int x, int y){
this.x = x;
this.y = y;
}
}
public class Main {
public static int answer;
public static int N;
public static int[][] visited;
int[] dx = {-1, -1, 1, 1};
int[] dy = { 1, -1, 1, -1};
public boolean isInside(int x, int y){
if(1<=x && x<=N && 1<=y && y<=N){
return true;
}else{
return false;
}
}
public void changeVisited(int row, int col, boolean flag){
for(int j=1; j<=N; j++){
if(flag){
visited[row][j] += 1;
}else{
visited[row][j] -= 1;
}
}
for(int i=1; i<=N; i++){
if(flag){
visited[i][col] += 1;
}else{
visited[i][col] -= 1;
}
}
if(flag){
visited[row][col] -= 1;
}else{
visited[row][col] += 1;
}
for(int i=0; i<4; i++){
int nx = row+dx[i];
int ny = col+dy[i];
while(isInside(nx, ny)){
if(flag){
visited[nx][ny] += 1;
}else{
visited[nx][ny] -= 1;
}
nx += dx[i];
ny += dy[i];
}
}
}
public void DFS(int row){
if(row == N+1){
answer++;
return;
}
for(int col=1; col<=N; col++){
if(visited[row][col] == 0){
changeVisited(row, col, true);
DFS(row+1);
changeVisited(row, col, false);
}
}
}
public static void main(String args[]) {
Main T = new Main();
arr = new ArrayList<>();
Scanner sc = new Scanner(System.in);
N = sc.nextInt();
answer = 0;
visited = new int[N+1][N+1];
T.DFS(1);
System.out.println(answer);
}
}
[참고 풀이]
import java.util.*;
public class Main {
public static int answer;
public static int N;
public static int[] col;
public boolean isAttackable(int r1, int c1, int r2, int c2){
if(c1 == c2) return true;
if( (r1+c1) == (r2+c2)) return true;
if( (r1-c1) == (r2-c2)) return true;
return false;
}
public void DFS(int row){
if(row == N+1){
answer++;
return;
}
for(int c=1; c<=N; c++){
boolean possible = true;
for(int i=1; i<=row-1; i++){
if(isAttackable(row, c, i, col[i])){
possible = false;
break;
}
}
if(possible == true){
col[row] = c;
DFS(row+1);
col[row] = 0;
}
}
}
public static void main(String args[]) {
Main T = new Main();
Scanner sc = new Scanner(System.in);
N = sc.nextInt();
col = new int[N+1];
answer = 0;
T.DFS(1);
System.out.println(answer);
}
}
4. 반성
- 문제를 다른 방식으로 해결할 수 있는가?
- 결과나 방법을 어떤 다른 문제에 활용할 수 있는가?
- 어떻게 하면 더 효율적으로 문제를 해결할 수 있는가?
- 어떻게 하면 더 효과적으로 문제를 해결할 수 있는가?
- 어떻게 하면 더 효율적으로 문제를 해결할 수 있는가?
-> visited를 int형 배열로 만들어서 활용한다
-> 방문한 곳을 다시 undo할 때의 로직에 주의해야 한다.
-> 불필요한 자료구조를 사용하지 않아야 한다.
- 어떻게 하면 더 효율적으로 문제를 해결할 수 있는가?
-> isAttackable 로직을 알아두자
-> col에 기록을 해두고, 그것을 활용할 수 있다.
-> 굳이 visited 배열을 만들어야 하는 것이 아니다.
'PS' 카테고리의 다른 글
| Reverse Linked List [Leetcode 206] (0) | 2022.09.09 |
|---|---|
| 부분 수열의 합 [BOJ 1182] (0) | 2022.09.09 |
| 연산자 끼워넣기 [BOJ 14888] (0) | 2022.09.09 |
| 영화감독 숌 [BOJ 1436] (0) | 2022.09.08 |
| 이진 트리 순회 [자바 알고리즘 문제 풀이] (0) | 2022.09.07 |