simDev1234
심플하고 차분하게
simDev1234
전체 방문자
오늘
어제
  • 분류 전체보기
    • Computer Science
      • Basic Math
      • Data Structure
      • Algorithm
      • Database
      • OS
    • Language
      • Java
      • Kotlin
      • SQL
    • Framework
      • Spring
      • Orm&Mapper
      • 프로젝트로 스프링 이해하기
      • 스프링 라이브러리
    • Infra
      • Cloud
      • Docker
      • Redis
      • AWS, Azure
      • Device
    • Etc
      • CleanCoding
    • Git,Github

블로그 메뉴

  • 홈
  • 태그
  • 방명록

공지사항

인기 글

태그

  • 404
  • 자바프로그래밍
  • scanner #next() #nextLine()
  • JVM메모리구조
  • controllerTest
  • 자바프로그램
  • 자바
  • 스프링
  • 자바메모리구조
  • null
  • 참조변수
  • 컨트롤러
  • 참조타입

최근 댓글

최근 글

티스토리

hELLO · Designed By 정상우.
simDev1234

심플하고 차분하게

Computer Science/Algorithm

[알고리즘] 백트래킹

2022. 8. 31. 22:08

|  백트래킹

- 모든 가능한 경우의 수 중에서 유망하지 않은 쪽은 제외하고 최적해를 구하는 방법

- 주로 재귀를 사용해서 구현한다.

유망(Promising) 가능성 있다.
가지치기(Pruning) 가능성 없는 것 제외하기
백트래킹(Backtracking) 유망하지 않은 쪽으로는 가지 않고 Back한다.

 

|  N-Queen 을 통한 백트래킹 이해

https://www.acmicpc.net/problem/9663

 

9663번: N-Queen

N-Queen 문제는 크기가 N × N인 체스판 위에 퀸 N개를 서로 공격할 수 없게 놓는 문제이다. N이 주어졌을 때, 퀸을 놓는 방법의 수를 구하는 프로그램을 작성하시오.

www.acmicpc.net

- N x N의 체스판에 N개의 퀸을 서로 공격할 수 없도록 배치한다고 할 때

- 메모리 공간 : 

(1) 각 행의 열을 짚어줄 배열

(2) 카운팅 변수

- Flow

(1) i번째 행의 각 열에 퀸을 배치한다.

(2) 유망여부 : 이전 행의 퀸 열의 상하좌우, 대각선에 해당되는가? 

- 2-1 ) YES : 다음 행으로 이동 

- 2-2 ) NO : 가지치기

(2) 모든 행을 다 돌은 경우, 방법의 수 카운팅

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.Arrays;

public class Main {

    static int[] board; // 각 행의 퀸 열 위치
    static int cnt = 0; // 전체 카운트 수
    static int nQueen(int n, int r){
        // 탈출문
        if (r == n) {
            cnt++;
            //System.out.println(Arrays.toString(board));
            return cnt;
        }

        // 구현문
        // r번째 행에 대하여
        for (int i = 0; i < n; i++) {
            // 열 위치값 지정
            board[r] = i;

            // promising
            if (isPromising(r, i)){
                nQueen(n, r + 1);
            }
        }

        return cnt;
    }

    static boolean isPromising(int r, int c) {
        // 현재 행 전까지 겹치는 부분 확인
        for (int i = 0; i < r; i++) {
            int pre_r = i;
            int pre_c = board[i];

            if (pre_c == c || r - pre_r == Math.abs(c - pre_c)){
                return false;
            }
        }

        return true;
    }

    public static void main(String[] args) throws Exception{
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

        int N = Integer.parseInt(br.readLine());

        board = new int[N];

        System.out.println(nQueen(N, 0));
    }
}

 

|  그 외에 백트래킹을 사용하는 예시

(1) Permutation(순열)을 구하는 알고리즘 

import java.util.Arrays;

public class Practice {

    // 순열
    static int cnt = 0;
    static boolean[] visited;
    static int[] out;
    static int solution(int[] arr, int n, int r) {
        visited = new boolean[n];
        out = new int[r];

        return permutation(arr, n, r, 0);
    }

    static int permutation(int[] arr, int n, int r, int depth){
        if (depth == r){
            cnt++;
            System.out.println(Arrays.toString(out));
            return cnt;
        }

        for (int i = 0; i < n; i++) {
            if (visited[i] == false) {
                visited[i] = true;
                out[depth] = arr[i];
                permutation(arr, n, r, depth + 1);
                out[depth] = 0;
                visited[i] = false;
            }
        }

        return cnt;
    }

    public static void main(String[] args) {
        int[] arr = { 1, 2, 3 };
        int n = 3; // n개의 수 중에
        int r = 2; // r개의 수를 고르는 방법
        System.out.println(solution(arr, n, r));
    }
}

(2) N자리수에서 앞자리부터 일의 자리수, 십의 자리수... N의 자리수가 모두 소수인 수를 찾는 알고리즘

- 첫번째 자릿수는 무조건 2,3,5,7중 하나가 들어가야한다.

- 두번재 자릿수부터 0 ~ 9 중에 유망한 수를 구한다.

  > 유망하다 : 2나 5로 나누어떨어지지 않는 수

     > 백트래킹 : 현재까지 자릿수의 숫자(ex.233)가 소수인지 확인

  > 유망하지X : 가지치기 

public class Practice2 {

    static void solution(int n) {
        // 첫번째 자릿수는 무조건 2, 3, 5, 7 중 하나
        int[] primes = {2, 3, 5, 7};

        for (int i = 0; i < primes.length; i++) {
            getPrimes(primes[i], n,1);
        }
    }

    static void getPrimes(int prime, int n, int digitLen){
        
        if (digitLen >= n){
            System.out.print(prime + " ");
            return;
        }

        // 두번째 자릿수부터는 0 - 9중에
        for (int i = 0; i < 10; i++) {
            // 가지치기 : 2 또는 5로 나누어떨어지지 않는 수
            if (i % 2 != 0 && i % 5 != 0) {
                int primeCandidate = 10 * prime + i;

                // backtracking : 소수이면
                if (isPrime(primeCandidate)){
                    getPrimes(primeCandidate, n,digitLen + 1);
                }
            }
        }
    }
    
    static boolean isPrime(int n) {

        if (n < 2) {
            return false;
        }

        for (int i = 2; i <= Math.sqrt(n); i++) {
            if (n % i == 0) {
                return false;
            }
        }
        return true;
    }

    public static void main(String[] args) {
        int n = 3;
        solution(n);
    }
}

 

|  백준 문제집

https://www.acmicpc.net/step/34

 

백트래킹 단계

삼성 SW 역량 테스트 기출 문제 1

www.acmicpc.net

 

[ 출처 및 참조 ]

부트캠프 수업 후 정리한 내용입니다.

 

'Computer Science > Algorithm' 카테고리의 다른 글

[알고리즘] 최단 경로 구하기 - 2. 벨만 - 포드  (0) 2022.09.01
[알고리즘] 최단 경로 구하기 - 1. 다익스트라  (0) 2022.09.01
[알고리즘] DP (동적 계획법)  (0) 2022.08.26
모듈러 산술  (0) 2022.08.25
[알고리즘] 분할정복  (0) 2022.08.25
    'Computer Science/Algorithm' 카테고리의 다른 글
    • [알고리즘] 최단 경로 구하기 - 2. 벨만 - 포드
    • [알고리즘] 최단 경로 구하기 - 1. 다익스트라
    • [알고리즘] DP (동적 계획법)
    • 모듈러 산술
    simDev1234
    simDev1234
    TIL용 블로그. * 저작권 이슈가 있는 부분이 있다면 댓글 부탁드립니다.

    티스토리툴바