๐ŸŒป JAVA/์•Œ๊ณ ๋ฆฌ์ฆ˜, ์ž๋ฃŒ๊ตฌ์กฐ

์•Œ๊ณ ๋ฆฌ์ฆ˜ - ๋ฐฑํŠธ๋ž˜ํ‚น(Back-Tracking)

iseunghan 2020. 12. 14. 16:00
๋ฐ˜์‘ํ˜•

๋ฐฑํŠธ๋ž˜ํ‚น ์ด๋ž€?

๋ฐฑํŠธ๋ž˜ํ‚น์€ ๋ชจ๋“  ์กฐํ•ฉ์˜ ์ˆ˜๋ฅผ ์‚ดํŽด๋ณด์ง€๋งŒ, ์กฐ๊ฑด์ด ๋งŒ์กฑํ•  ๋•Œ๋งŒ ์‚ดํŽด๋ณด๊ธฐ ๋•Œ๋ฌธ์—

์–ด๋–ค ๊ฒฝ์šฐ์— ๋”ฐ๋ผ ํ›จ์”ฌ ๋น ๋ฅผ์ˆ˜๋„ ์žˆ๋‹ค.

 

 

๋ฐฑํŠธ๋ž˜ํ‚น ์‹คํ–‰ ์ˆœ์„œ

๋ฐฑํŠธ๋ž˜ํ‚น์€ DFS(๊นŠ์ด ์šฐ์„  ํƒ์ƒ‰)์„ ๋จผ์ € ์‹คํ–‰ํ•˜๋ฉด์„œ ๋” ์ด์ƒ ํƒ์ƒ‰์„ ์ง„ํ–‰ํ•  ์ˆ˜ ์—†๋Š” ์ƒํ™ฉ์ด๋ฉด ๋‹ค์‹œ ๋˜๋Œ์•„ ๊ฐ€์„œ(๋ฐฑํŠธ๋ž˜ํ‚น) ํƒ์ƒ‰์„ ์ง„ํ–‰ํ•œ๋‹ค.

 

๊ด€๋ จ ๋ฌธ์ œ๋ฅผ ํ’€์–ด๋ณด๋ฉด ์ดํ•ด๊ฐ€ ์ž˜ ๋  ๊ฒƒ์ด๋‹ค. 

 

www.acmicpc.net/step/34

 

๋ฐฑํŠธ๋ž˜ํ‚น ๋‹จ๊ณ„

์กฐ๊ธˆ ๋” ๋ณต์žกํ•œ ๋ฐฑํŠธ๋ž˜ํ‚น ๋ฌธ์ œ 1

www.acmicpc.net

 

 

N๊ณผ M (1) ํ’€์–ด๋ณด๊ธฐ


์ž์—ฐ์ˆ˜ N์ด ์ฃผ์–ด์ง€๋ฉด 1๋ถ€ํ„ฐ N๊นŒ์ง€ ์ž์—ฐ์ˆ˜ ์ค‘์—์„œ ์ค‘๋ณต ์—†์ด M๊ฐœ๋ฅผ ๊ณ ๋ฅธ ์ˆ˜์—ด์„ ์ถœ๋ ฅํ•˜๋ฉด ๋œ๋‹ค.

์˜ˆ๋ฅผ ๋“ค์–ด,

N : 3 , M : 3 ์ผ๋•Œ, ์ค‘๋ณต ์—†์ด ์•„๋ž˜ ์ฒ˜๋Ÿผ ์ถœ๋ ฅ์‹œํ‚ค๋ฉด ๋œ๋‹ค.

------------------------------------------------

1   2   3
1   3   2
2   1   3
2   3   1
3   1   2
3   2   1

 

์ผ๋‹จ for๋ฌธ์„ ๋Œ๋ฉด์„œ

for(int i=1; i<=N; i++) {
    arr[index] = i; // i๋ฅผ ๋ฐฐ์—ด์— ๋„ฃ๋Š”๋‹ค.
    visited[i] = true; // i๋ฅผ ๋ฐฉ๋ฌธํ–ˆ๋‹ค๊ณ  ์ฒดํฌ
	recursion(index + 1); // ๋‹ค์Œ ์ธ๋ฑ์Šค ์›์†Œ๋ฅผ ๋„ฃ๊ธฐ ์œ„ํ•ด (index+1)์žฌ๊ท€ ํ˜ธ์ถœ์„ ํ•œ๋‹ค.
	visited[i] = false; // ์œ„์— recursion์ด ๋๋‚ฌ์œผ๋ฏ€๋กœ, ๋‹ค์Œ i๋กœ ๋„˜์–ด๊ฐ€๊ธฐ ์ „์— ํ˜„์žฌ i์˜ ๋ฐฉ๋ฌธ์—ฌ๋ถ€๋ฅผ false๋กœ ๋ฐ”๊ฟ”์ค€๋‹ค.
}

 

  • 1-1) i = 1 ์ผ ๋•Œ

1์„ ๋ฐฉ๋ฌธํ–ˆ๋‹ค๊ณ  ํ‘œ์‹œํ•œ ๋’ค, ๋‹ค์Œ 1์„ ๋ฐฉ๋ฌธํ•  ๋•Œ -> ์ด๋ฏธ ๋ฐฉ๋ฌธ ํ–ˆ์œผ๋ฏ€๋กœ ๊ฑด๋„ˆ ๋›ฐ๊ฒŒ ๋œ๋‹ค. (ํ•ด๋‹น i์˜ visited ๊ฐ’ ํ™•์ธ)

// visited [O,X,X]

for(int i=1; i<=N; i++) {
	if(!visited[i]) {
		// ๋ฐฉ๋ฌธ ์—ฌ๋ถ€ ํ™•์ธ! (์•ˆํ–ˆ์„ ๊ฒฝ์šฐ์—๋งŒ ์‹คํ–‰)
		visited[i] = true; // ๋ฐฉ๋ฌธ ์•ˆํ–ˆ์œผ๋ฉด ํ•ด๋‹น i์˜ visited ๊ฐ’์„ true๋กœ ๋ณ€๊ฒฝ!
	}  
}

 

  • 1-2) ํ˜„์žฌ i๋Š” 2์ด๋‹ค.

๊ทธ๋‹ค์Œ 2๋ฅผ ๋ฐฉ๋ฌธํ• ๋•Œ๋Š” visited[2] = false ์ด๋ฏ€๋กœ ๋ฐฉ๋ฌธ ํ•œ๋‹ค.

 

๋˜ for๋ฌธ์œผ๋กœ 1,2,3์„ ์žฌ ๋ฐฉ๋ฌธ์„ ํ•˜๊ธฐ์ „์—,  i = 1, 2 -> ์ด๋ฏธ ๋ฐฉ๋ฌธ ํ–ˆ๊ธฐ ๋•Œ๋ฌธ์— ๊ฑด๋„ˆ ๋›ฐ๊ฒŒ ๋˜๊ณ , 3 ์€ visited[3] = false ์ด๊ธฐ ๋•Œ๋ฌธ์—, ๋ฐฉ๋ฌธํ•  ์ˆ˜ ์žˆ๋‹ค.

//visited [O,O,X]

for(int i=1; i<=N; i++) {
	if(!visited[i]){
		// i=3์ผ ๊ฒฝ์šฐ์—๋งŒ ํ•ด๋‹น!
        visited[3] = true;
        arr[index] = 3;
        recursion(index + 1);
	}
}

 

์žฌ๊ท€ ํ˜ธ์ถœ์„ ํ• ๋•Œ ๋„˜๊ฒจ์ฃผ๋Š” index๊ฐ’์ด M๊ณผ ๊ฐ™์•„ ์ง€๋Š” ์‹œ์ ์— ์ถœ๋ ฅ์„ ํ•˜๋„๋ก ํ•œ๋‹ค.

// visited [O,O,O]
// arr [1,2,3]
// index = 3 , M = 3

if(index == M){ // ๋„˜๊ฒจ ๋ฐ›์€ index๊ฐ€ M๊ณผ ๊ฐ™์•„์ง€๋Š” ์‹œ์ ์— ์‹คํ–‰
	for(int i=0; i<M; i++){
    	System.out.print(arr[i] + " ");
    }
    System.out.println();
}

 

  • 1-3) ํ˜„์žฌ i๋Š” 3์ด๋‹ค.

์—ฌ๊ธฐ์„œ ์šฐ๋ฆฌ๊ฐ€ 3์„ ๋ฐฉ๋ฌธ ํ•  ์ˆ˜ ์žˆ๋Š” ์ด์œ ๋Š”? ์šฐ๋ฆฌ๋Š” ์ „์— 1 -> 2-> 3 ์ˆœ์œผ๋กœ ๋ฐฉ๋ฌธ์„ ํ–ˆ๊ธฐ ๋•Œ๋ฌธ์— visited[3]=true๋กœ ์„ค์ • ๋˜์–ด ์žˆ์„ ๊ฒƒ์ด๋‹ค. 

 

์ด์ „์— 1->2->3์„ ์ข…๋ฃŒ ํ•œ ๋’ค์—, ๋‹ค์‹œ visited[3]์„ false๋กœ ๋ฐ”๊ฟ” ์ฃผ์–ด์•ผ ํ•˜๊ณ ,

๋‹ค์‹œ 1->2๋ฅผ ์ข…๋ฃŒ ํ•  ๋•Œ๋„, visited[2]๋ฅผ false๋กœ ๋ฐ”๊ฟ” ์ฃผ์–ด์•ผ ํ•œ๋‹ค.

 

์ด๊ฒƒ์„ ์ฝ”๋“œ๋กœ ๋‚˜ํƒ€ ๋‚ด๋ฉด ?

for(int i=1; i<=N; i++) {
	arr[index] = i;
	visited[i] = true;
	recursion(index + 1);
    // recursion์ด ๋๋‚˜๋ฉด, ์ž์‹ ๋…ธ๋“œ๋ฅผ ๋ฐฉ๋ฌธ์„ ๋‹คํ–ˆ๋‹ค๋Š” ์˜๋ฏธ์ด๋ฏ€๋กœ ๋‹ค์‹œ visited[i] = false๋กœ ๋ณ€๊ฒฝ
	visited[i] = false; // * ์ด ๋ถ€๋ถ„!
}

 

๊ทธ๋Ÿผ ๋‹ค์‹œ ์ด์ „ ๋‹จ๊ณ„๋กœ ๋˜๋Œ์•„ ๊ฐ€๋ฉด,

  • 1-3) i = 3์ผ ๋•Œ

visited[3] = true๋กœ ์ฒดํฌ ํ•ด์ฃผ๊ณ , ๋„˜๊ฒจ ๋ฐ›์€ index(2)์— i๊ฐ’์ธ 3์„ ๋„ฃ์–ด์ค€๋‹ค.

// visited [O,X,O]
for(int i=1; i<=N; i++) {
	if(!visited[i]){
    	visited[i] = true;
        arr[index] = i;
        recursion(index + 1);
        visited[i] = false;
    }
}

๊ทธ๋ฆฌ๊ณ  ๋‹ค์Œ 1,2,3 ๋…ธ๋“œ๋“ค์„ ๋ฐฉ๋ฌธ์„ ํ•˜๊ฒŒ ๋˜๋ฉด,

 

  • 1-3-2) visited[1], visited[3] = true;

์œ ์ผํ•˜๊ฒŒ ๋‚จ์€ ๋…ธ๋“œ๋Š” 2์ด๋ฏ€๋กœ visited[2] = true, ๋„˜๊ฒจ ๋ฐ›์€ index์— ํ˜„์žฌ i(2)๊ฐ’์„ ๋„ฃ์–ด์ค€๋‹ค.

// visited [O,O,O]
// arr [1,3,2]
// index = 2, M = 3

for(int i=1; i<=N; i++) {
// 1, 3 ๊ฑด๋„ˆ ๋œ€. i=2์ผ ๋•Œ๋งŒ ์‹คํ–‰
	if(!visited[2]){
    	visited[2] = true;
        arr[index] = 2;
        recursion(index + 1);
        visited[2] = false;
    }
}

์—ฌ๊ธฐ์„œ recursion(index + 1) -> recursion(3) ์„ ํ˜ธ์ถœํ•˜๊ฒŒ ๋˜๋ฉด,

if(index == M){ // index : 3, M : 3
	for(int i=0; i<M; i++) {
    	System.out.print(arr[i] + " ");
    }
    System.out.println();
}	

์ถœ๋ ฅ

1  3  2

 

์ด๋Œ€๋กœ ๊ณ„์† ๋ฐ˜๋ณตํ•˜๋ฉด ๋œ๋‹ค.

 

์ „์ฒด ์ฝ”๋“œ

import java.io.*;
import java.util.StringTokenizer;

public class Main {
    static int N, M;
    static int[] arr;
    static boolean[] isUsed;
    static BufferedWriter bw;
    public static void main(String[] args) throws IOException {
        BufferedReader bf = new BufferedReader(new InputStreamReader(System.in));
        bw = new BufferedWriter(new OutputStreamWriter(System.out));
        StringTokenizer st = new StringTokenizer(bf.readLine());

        N = Integer.parseInt(st.nextToken());
        M = Integer.parseInt(st.nextToken());

        arr = new int[M+1];
        isUsed = new boolean[N+1];

        recursion(0);

        bw.flush();
        bw.close();
    }

    private static void recursion(int K) throws IOException {
        if (K == M) { // ๋ชจ๋“  ๋ฐฐ์—ด์˜ ์›์†Œ๊ฐ€ ์ฐผ์„ ๋•Œ,
            for (int i = 0; i < M; i++) {
                bw.write(arr[i] + " ");
                // ๋งŒ์•ฝ ์—ฌ๊ธฐ์„œ ๋ฐฐ์—ด์˜ ๋“ค์–ด์žˆ๋Š” ๊ฐ’์˜ ๋ฐฉ๋ฌธ์—ฌ๋ถ€๋ฅผ false๋กœ ํ•ด์ฃผ๋Š”๊ฑด? -> ๊ทธ๋Ÿฌ๋ฉด ๋‹ค์‹œ ๋Œ์•„๊ฐ”์„ ๋•Œ, ์ค‘๋ณต์ด ๋‚˜์˜ค๊ฒŒ ๋œ๋‹ค.
                // ex) isUsed[arr[i]] = false; ? ์–ด๋–ป๊ฒŒ ๋ ๊นŒ?? X
            }
            bw.write("\n");
            return ;
        }

        for (int i = 1; i <= N; i++) { // [1, ] [2, ] [3, ] ์ด๋Ÿฐ์‹์œผ๋กœ ํ˜ธ์ถœํ•˜๊ฒŒ๋”
            if (!isUsed[i]) { // ์‚ฌ์šฉ ์•ˆํ–ˆ์„ ๋•Œ๋งŒ, ์‹คํ–‰
                arr[K] = i; // arr[์ธ๋ฑ์Šค]์— i๊ฐ’์„ ๋„ฃ์–ด์ฃผ๊ณ 
                isUsed[i] = true; // ๋ฐฉ๋ฌธ ์—ฌ๋ถ€ ํ‘œ์‹œ!
                recursion(K + 1); // ๋ฐฐ์—ด์˜ ๋‹ค์Œ ์นธ์„ ์ฑ„์šฐ๊ธฐ ์œ„ํ•ด์„œ K๋ฅผ +1ํ•ด์ฃผ๊ณ  ๋‹ค์‹œ ์žฌ๊ท€๋กœ ๋Œ๋ฆฐ๋‹ค. K++๋ฅผ ํ•ด์ฃผ๋ฉด ์•ˆ๋˜๋Š” ์ด์œ : for๋ฌธ์„ ๋Œ๋ ธ์„๋•Œ, IndexOutOfBoundExcepiton ๋ฐœ์ƒ ๊ฐ„์œผ!
                isUsed[i] = false; // recursion์ด ๋‹ค ์ˆ˜ํ–‰๋๋‹ค๋ฉด, ์ถœ๋ ฅ๋„ ๋๋‚ฌ๋‹ค๋Š” ์˜๋ฏธ์ด๋‹ˆ, ์ด์ œ ํ•ด๋‹น i๊ฐ’์ด ์œ ์ง€๋ ๋•Œ, ๋ฐฉ๋ฌธ์—ฌ๋ถ€๋ฅผ ์—†์• ์ค€๋‹ค.(์–ด์ฐจํ”ผ ํ˜„์žฌ for๋ฌธ์€ ์ด์ „ i๊ฐ’์„ ์‚ฌ์šฉ ์•ˆํ•œ๋‹ค.)
            }
        }
    }
}

 

๋ฐ˜์‘ํ˜•