반응형
이번에는 백준 15651번 문제를 통해 백트래킹 알고리즘 학습을 강화해 보자.
이쯤되면 점점 익숙해질 것이다.

문제 핵심

    • 1부터 N까지의 자연수 중 중복 없이 M개를 고른 수열
    • 1 <= M <= N <= 7
    • 중복하여 방문 가능

풀이 과정

이전 풀이를 보았다면 바로 생각이 날 수도 있다.

모든 경로가 중복 방문이 가능하다면? 다시 처음부터 시작하면 된다.

우리는 무조건 1부터 시작하는 조건을 가지고 있다. 그렇다면 변동하던 시작값을 고정시켜버리면 항상 중복하여 방문하게 된다.

핵심 코드

start 매개변수를 제외 시키고 반복문의 시작값을 0으로 고정하였다.

private static void backTracking(int depth, int M, int N) {
    if (depth == M) {
        for (int i : arr) {
            stringBuilder.append(i).append(" ");
        }
        stringBuilder.append("\n");
        return;
    }

    for (int i = 0; i < N; i++) {
        arr[depth] = i + 1;
        backTracking(depth + 1, M, N);
    }
}

 

 

반복하여 진행하니 점점 한 눈에 알아볼 정도로 난이도가 내려가고 있다. ( 아니면 죄송...)
다음 4번째 N과 M을 끝으로 이해도를 높이길 바란다.

전체 코드

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.StringTokenizer;

public class Main {

    private static int[] arr;
    private static StringBuilder stringBuilder = new StringBuilder();

    private static void backTracking(int depth, int M, int N) {
        if (depth == M) {
            for (int i : arr) {
                stringBuilder.append(i).append(" ");
            }
            stringBuilder.append("\n");
            return;
        }

        for (int i = 0; i < N; i++) {
            arr[depth] = i + 1;
            backTracking(depth + 1, M, N);
        }
    }

    public static void main(String[] args) throws IOException {
        BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer stringTokenizer = new StringTokenizer(bufferedReader.readLine());

        int N = Integer.parseInt(stringTokenizer.nextToken());
        int M = Integer.parseInt(stringTokenizer.nextToken());

        arr = new int[M];


        backTracking(0, M, N);

        System.out.println(stringBuilder);

    }
}
반응형
반응형

 

이번에는 백준 15650번 문제를 통해 백트래킹 알고리즘 학습을 강화해 보자.
저번 15649번 문제에서 살짝 변형된 문제이다.

문제 핵심

  • 1부터 N까지의 자연수 중 중복 없이 M개를 고른 수열
  • 1 <= M <= N < 8
  • 오름차순이여야 한다.

풀이 과정

저번에는 모든과정을 체크했다면 이번 문제는 앞에 숫자가 커짐에 따라 끝의 숫자의 개수가 작아지므로 ( 즉, 오름차순이므로 ) 앞에 숫자 기준으로만 생각하면 된다. 다음 그림과 같이 진행된다. N = 4, M = 2 기준

 

1. 배열 첫 번째 요소를 채워 넣는다. 

2. 두번 째 요소를 넣기 위해 다시 함수를 호출하여 1-1로 진행한다.

3. 두번 째 요소를 넣은 후 다시 함수를 호출하고 깊이와 M값이 같기 때문에 출력한 후 반환한다.

4. 1-1 안에 배열에서 i 값이 증가한 1-2 와 같이 진행되어 이를 N값 전까지 반복한다.

 

private static void backTracking(int depth, int M, int N, int start) {
    if (depth == M) {
        for (int i : arr) {
            stringBuilder.append(i).append(" ");
        }
        stringBuilder.append("\n");
        return;
    }

    for (int i = start; i < N; i++) {
        arr[depth] = i + 1;
        backTracking(depth + 1, M, N, i + 1);
    }
}

오랜만에 뵙습니다. 취준 준비중 생활적 요소가 부족하여
두달가량 일용직 근무를 다녀왔습니다.
다시 천천히 시작해 보려고 합니다. 기다려 주셔서 감사합니다.

 

전체 코드

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.StringTokenizer;


public class Main {

    private static int[] arr;
    private static StringBuilder stringBuilder = new StringBuilder();

    private static void backTracking(int depth, int M, int N, int start) {
        if (depth == M) {
            for (int i : arr) {
                stringBuilder.append(i).append(" ");
            }
            stringBuilder.append("\n");
            return;
        }

        for (int i = start; i < N; i++) {
            arr[depth] = i + 1;
            backTracking(depth + 1, M, N, i + 1);
        }
    }


    public static void main(String[] args) throws IOException {
        BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer stringTokenizer = new StringTokenizer(bufferedReader.readLine());

        int N = Integer.parseInt(stringTokenizer.nextToken());
        int M = Integer.parseInt(stringTokenizer.nextToken());

        arr = new int[M];


        backTracking(0, M, N, 0);

        System.out.println(stringBuilder);

    }
}

 

반응형
반응형
요즘 시험이니 일이니 핑계 거리가 생겨 포스팅이 많이 늦어졌습니다. 
다시 매일 노력하여 포스팅 하도록 노력하겠습니다. 감사합니다.

이번에는 백준 15649번 문제를 통해 백트래킹 알고리즘을 실습해 보자. 

백트래킹이란 간단히 설명하면
가능한 모든 경로 탐색 중 조건이 맞지 않으면 이전 단계로 돌아가 다시 탐색하는 알고리즘이다.

 


 

문제 핵심

  • 1부터 N까지의 자연수 중 중복 없이 M개를 고른 수열
  • 1 <= M <= N < 8

풀이 과정

반복과 재귀를 통해 깊이에 따라 값을 처리한다.

dfs를 참고할 수 있겠다.

핵심 코드

  1. 현재 깊이를 체크한다.
    1. 최대 깊이에 도달한다면 리스트 값을 저장하고 리턴한다.
  2. 반복문을 통해 방문되지 않은 리스트 요소를 특정하여 방문한다.
  3. 리스트 현재 깊이 인덱스에 값을 저장한다. 
  4. 재귀를 통해 다음 깊이로 이동한다.
  5. false를 통해 방문을 초기화 하고 이전으로 이동
private static void backTracking(int depth, int M, int N) {
    if(depth == M) {
        for(int i : arr) {
            stringBuilder.append(i).append(" ");
        }
        stringBuilder.append("\n");
        return;
    }

    for(int i = 0; i < N; i++) {
        if(!visited[i]) {
            visited[i] = true;
            arr[depth] = i + 1;
            backTracking(depth + 1, M, N);
            visited[i] = false;
        }
    }
}

EX) N : 4, M : 2

  1. N과 M이 위와 같을 때 1회전의 경우 다음과 같이 진행된다.
  2. 이후 depth + 1을 통해 M과 같아지게 되므로 저장 후 리턴된다.
  3. 마지막 방문했던 인덱스를 false를 통해 이전으로 돌아온다.
    1. 이 때 arr 배열에는 이후 값을 덮어쓰기 때문에 제거할 필요 없다.

 

 

다소 난해하지만, 재귀 방식을 이용한다면 풀 수 있는 문제이다.
이번 풀이에서는 DFS와 비슷하다고 볼 수 있다.
일정 깊이까지 도달한 후 다시 돌아오는 알고리즘으로
디버깅을 통해 로직이 진행되는 순서를 확인하면 좋겠다.

전체 코드

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.StringTokenizer;

public class Main {
    private static int [] arr;
    private static boolean [] visited;
    private static StringBuilder stringBuilder = new StringBuilder();

    private static void backTracking(int depth, int M, int N) {
        if(depth == M) {
            for(int i : arr) {
                stringBuilder.append(i).append(" ");
            }
            stringBuilder.append("\n");
            return;
        }

        for(int i = 0; i < N; i++) {
            if(!visited[i]) {
                visited[i] = true;
                arr[depth] = i + 1;
                backTracking(depth + 1, M, N);
                visited[i] = false;
            }
        }
    }

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

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

        arr = new int[M];
        visited = new boolean[N];

        backTracking(0, M, N);

        System.out.println(stringBuilder);
    }
}
반응형

+ Recent posts