티스토리 뷰

BAEKJOON

[9663]N-Queen (Backtracking)

IT공부블로그 2019. 7. 24. 12:44
728x90
반응형

Backtracking (되추적)


말이 존나어려운데 쉽게 말하면

어떤 노드의 유망성 점검후 유망하지않으면 그 노드의 부모 노드로 되돌아간다


예를들면 어떤길을 따라 쭉 가는데 길이 막혀있으면 마지막으로 만났던 갈림길로 되돌아가서 다른길로 가는거를 생각하면 되겠다.

Stack을 이용


자세한글은 https://idea-sketch.tistory.com/29 이분의 글을 참조


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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
import java.util.Scanner;
import java.util.Stack;
 
class Point {
    
    private int x;
    private int y;
    
    public Point(int x, int y) {
        this.x = x;
        this.y = y;
    }
    
    public int getX() {
        return x;
    }
    public void setX(int x) {
        this.x = x;
    }
    public int getY() {
        return y;
    }
    public void setY(int y) {
        this.y = y;
    }
}
 
public class Main {
 
    public static void main(String[] args) {
        
        int chessBoardSize = inputValueScanner();
        int[][] chessBoard = makeChessBoard(chessBoardSize);
        Stack<Integer> hopefulPointStack = new Stack<>();
        int chessBoardLen = chessBoard[0].length;
        int n_QueenPlaceCount = 0;
 
        firstHopefulPointInsert(hopefulPointStack, chessBoardLen);
        
        first:while!hopefulPointStack.isEmpty() ){
            
            int hopefulPointX = hopefulPointStack.pop();
            int hopefulPointY = hopefulPointStack.pop();
            Point hopefulPoint = new Point(hopefulPointX, hopefulPointY);
            
            chessBoard[hopefulPointX][hopefulPointY] = hopefulPointX + 1;
            boolean checkPlaceableQueenSeat = false;
            
            for(int queenCount = hopefulPointX; queenCount < chessBoardLen;){
                
                setLeftBottomDiagonalXvalueOfChessBoard(hopefulPoint, chessBoard);
                setCenterBottomStraightXvalueOfChessBoard(hopefulPoint, chessBoard);
                setRightBottomDiagonalXvalueOfChessBoard(hopefulPoint, chessBoard);
                
                queenCount++;
                
                // 퀸을 각 줄에 1개씩 다놓았을때
                if( queenCount == chessBoardLen){
                    n_QueenPlaceCount++;
                    // 체스판 초기화 코드 넣어야함
                    if(!hopefulPointStack.isEmpty()){
                        resetFlagIfUnplaceableQueen(hopefulPointStack.peek(), chessBoard);
                    }
                    break;
                }
                
                for(int y = chessBoardLen - 1; y >= 0; y--){
                    // 다음줄에 퀸을 놓을수있는지 확인
                    if( chessBoard[queenCount][y] == 0){
                        checkPlaceableQueenSeat = true;
                        hopefulPointStack.push(y);
                        hopefulPointStack.push(queenCount);
                    }
                }
                
                // 퀸을 놓을자리가 없다면
                if(!checkPlaceableQueenSeat){                    
                    if(!hopefulPointStack.isEmpty()){
                        resetFlagIfUnplaceableQueen(hopefulPointStack.peek(), chessBoard);
                    }
                }
                                
                break;
            }
        }
        
        System.out.println(n_QueenPlaceCount);
    }
    
    public static int inputValueScanner(){
        Scanner scan = new Scanner(System.in);
        return scan.nextInt();
    }
    public static int[][] makeChessBoard(int chessBoardSize){
        return new int[chessBoardSize][chessBoardSize];
    }
    
    public static void firstHopefulPointInsert(Stack<Integer> hopefulPointStack, int chessBoardLen){
        for(int i = chessBoardLen - 1; i >= 0; i--){
            hopefulPointStack.push(i);
            hopefulPointStack.push(0);
        }
    }
    
    public static void setLeftBottomDiagonalXvalueOfChessBoard(Point hopefulPoint, int[][] chessBoard){
        
        int hopefulPointX = hopefulPoint.getX();
        int minusYvalueContain = hopefulPoint.getY();
 
        for(int x = hopefulPointX; (x + 1< chessBoard[0].length; x++){
            for(int y = minusYvalueContain; (y - 1>= 0;){
                if( chessBoard[x+1][y-1== 0){
                    chessBoard[x+1][y-1= hopefulPointX + 1
                }
                
                minusYvalueContain = y-1;
                break;
            }
        }
    }
    
    public static void setCenterBottomStraightXvalueOfChessBoard(Point hopefulPoint, int[][] chessBoard){
        
        int hopefulPointY = hopefulPoint.getY();
        int hopefulPointX = hopefulPoint.getX();
        
        for(int x = hopefulPoint.getX(); (x + 1< chessBoard[0].length; x++){
            if( chessBoard[x+1][hopefulPointY] == 0){
                chessBoard[x+1][hopefulPointY] = hopefulPointX + 1;
            }
        }
    }
    
    public static void setRightBottomDiagonalXvalueOfChessBoard(Point hopefulPoint, int[][] chessBoard){
        
        int hopefulPointX = hopefulPoint.getX();
        int plusYvalueContain = hopefulPoint.getY();
        
        for(int x = hopefulPointX; (x + 1< chessBoard[0].length; x++){
            for(int y = plusYvalueContain; (y + 1< chessBoard[0].length;){
                
                if( chessBoard[x+1][y+1== 0){
                    chessBoard[x+1][y+1= hopefulPointX + 1;                     
                }
                plusYvalueContain = y + 1;
                break;
            }
        }
    }
    
    public static void resetFlagIfUnplaceableQueen(int flagValue, int[][] chessBoard){
        
        for(int x = flagValue; x < chessBoard[0].length; x++){
            for(int y = 0; y < chessBoard[0].length; y++){
                if( chessBoard[x][y] > flagValue){ // 다시 처음부터 해야한다면 다지워야하니 값보다 큰건 다지움
                    chessBoard[x][y] = 0;
                }
            }
        }
    }
 
}
cs


위 코드의 핵심은 Stack이다.

스택안에 유망한 노드의 좌표를 넣어서 막힐때마다 스택안의 값을 꺼내어 다시 계산한다 

최대한 클린코드가 말한대로 나름 신경써서 코드를 작성했기에 

먼 미래의 내가 볼때도 제발 무리가 없길 바란다.

728x90
반응형

'BAEKJOON' 카테고리의 다른 글

[10974] 모든 순열  (0) 2019.07.22
댓글
반응형
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
TAG
more
«   2024/05   »
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 31
글 보관함