[#22] 백트래킹 + 위상 정렬

2025. 2. 25. 10:58·LG 유플러스 유레카 SW/Algorithm
목차
  1. 백트래킹
  2. 위상 정렬(Topological Sorting)

백트래킹

해를 찾기 위해서 후보군을 나열하고, 만약 조건에 맞지 않다면 후보군에서 제외하고 돌아와 다음 후보군을 찾는 방식
  • 트리 구조를 기반으로 DFS 방식을 진행하면서 각 루트에 대해 조건에 부합했는 체크(Promising)
  • 만약 해당 트리에서 조건에 맞지 않는 노드를 발견한다면, 더 이상 탐색을 멈추고, 다른 노드로 가기 위해 현재 가지를 버림(Pruning)
  • 백트래킹에서 검색할 후보들을 상태 공간 트리(State Space Tree)로 표현

 

👩🏻‍💻 문제 풀어보기: N-Queens

package graph;

import java.util.LinkedList;
import java.util.List;

public class 백트래킹_NQueens {
	static int N = 4;
	static List<Position> promise = new LinkedList<>();
	static int promiseSetCnt;
	public static void main(String[] args) {
		dfs(0);
		System.out.println(promiseSetCnt);

	}

	static void dfs(int curRow) {
		if(curRow == N) {
			promiseSetCnt++; // 완성된 세트를 카운트
			return;
		}
		for (int col = 0; col < N; col++) {
			if (isSafe(curRow, col)) { // 이 위치가 유망하면
				promise.add(new Position(curRow, col));
				dfs(curRow + 1);
				promise.remove(promise.size()-1); // 백트래킹: 마지막으로 추가한 퀸 제거
			}

		}
	}

	static boolean isSafe(int curRow, int col) {
		for (Position queen : promise) {
			// 유망 목록에 들어가 있는 퀸들과 열이 같으면 탈락
			if (col == queen.col) return false;
			// 유망 목록에 들어가 있는 퀸들의 대각선(|X1 - X2| = |Y1 - Y2|)에 있으면 탈락
			if (Math.abs(queen.row - curRow) == Math.abs(queen.col - col)) return false;

		}
		return true;
	}

	// 퀸의 위치를 담고 있는 클래스
	static class Position {
		int row, col;

		public Position(int row, int col) {
			super();
			this.row = row;
			this.col = col;
		}

		@Override
		public String toString() {
			return "Position [row=" + row + ", col=" + col + "]";
		}

	}
}
  • 시간복잡도: O(n!)
    • 8-Queens라면 8^8 = 16,000,000이 넘는 경우의 수를 확인해야 하는데 Pruning을 하면 약 4000 ~ 5000 정도만 탐색하여 92개의 해를 얻게 됨.

 

🍔 부분 집합으로 구현한 햄버거 다이어트 문제를 백트래킹 해보기

/*
	입력
	1
	5 1000
	100 200
	300 500
	250 300
	500 1000
	400 400
	
	출력
	#1 750
*/

package 순조부;

import java.util.Scanner;

public class SWEA_햄버거다이어트_백트래킹 {
	static int N, L;
	static int[] tastes, cals;
	static boolean[] isSelected;
	static int result;
	static StringBuilder sb = new StringBuilder();

	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		int T = sc.nextInt();

		for (int tc = 1; tc <= T; tc++) {
			N = sc.nextInt(); // 재료의 수
			L = sc.nextInt(); // 기준 총 칼로리

			tastes = new int[N];
			cals = new int[N];

			isSelected = new boolean[N];

			for (int i = 0; i < N; i++) {
				tastes[i] = sc.nextInt(); // 각 재료의 맛 점수
				cals[i] = sc.nextInt(); // 각 재료의 칼로리
			}

			result = 0;

			subset(0, 0, 0);
			sb.append("#").append(tc).append(" ").append(result).append("\n");
		}

		System.out.println(sb);
		sc.close();

	}

	private static void subset(int cnt, int tastesSum, int calsSum) {
		// 백트래킹
		if (calsSum > L) { // 칼로리 합이 기준 칼로리를 넘어버리면 이 결과 집합 세트는 버림
			return;
		}

		if (cnt == N) {
			result = Math.max(tastesSum, result);
			return;
		}

		subset(cnt + 1, tastesSum + tastes[cnt], calsSum + cals[cnt]);

		subset(cnt + 1, tastesSum, calsSum);

	}

}

 

위상 정렬(Topological Sorting)

방향 그래프의 정점들을 선형으로 배열하는 방법으로, 주로 의존성 문제에서 사용
  • 사이클이 없을 때만 가능

출처: https://www.geeksforgeeks.org/topological-sorting/

 

위상 정렬 방법

  1. 진입 차수 계산: 각 정점의 진입 차수(해당 정점으로 들어오는 간선의 수)를 계산
  2. 큐에 추가: 진입 차수가 0인 정점을 큐에 추가
  3. 정점 처리: 큐에서 정점을 하나씩 꺼내 결과 리스트에 추가하고, 그 정점과 연결된 모든 정점의 진입 차수를 감소시킴. 만약 진입 차수가 0이 되는 정점이 있다면 큐에 추가
  4. 결과 학인: 모든 정점을 처리했는지 확인. 처리된 정점의 수가 원래 정점의 수와 같다면 위상 정렬이 성공한 것

 

👩🏻‍💻 문제 풀어보기: 백준_문제집_1766

/* 위상 정렬 */

/*
	입력
	4 2
	4 2
	3 1
	
	출력
	3 1 4 2
	
	조건
	1.N개의 문제는 모두 풀어야 한다.
	2.먼저 푸는 것이 좋은 문제가 있는 문제는, 먼저 푸는 것이 좋은 문제를 반드시 먼저 풀어야 한다.
	3.가능하면 쉬운 문제부터 풀어야 한다.
*/

package graph;

import java.util.ArrayList;
import java.util.List;
import java.util.PriorityQueue;
import java.util.Scanner;

public class 백준_문제집_1766 {

	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);

		int N = sc.nextInt();
		int M = sc.nextInt();

		// 그래프를 위한 인접 리스트 초기화
		List<List<Integer>> graph = new ArrayList<>(N + 1);
		for (int i = 0; i <= N; i++) {
			graph.add(new ArrayList<>());
		}
		
		// 진입 차수 배열 초기화
		int[] inDegree = new int[N+1];

		// 의존 관계 입력 처리
		for (int i = 0; i < M; i++) {
			int a = sc.nextInt(); // 선행 문제
			int b = sc.nextInt(); // 후행 문제
			graph.get(a).add(b); // 그래프에 간선 추가 
			inDegree[b]++; // 후향 문제의 진입 차수 증가
		}
		
		// 위상 정렬을 위한 최소 힙(우선순위 큐) 초기화
		// 3번 조건 때문에 pq로 해야 함
		PriorityQueue<Integer> pq = new PriorityQueue<>();
		
		for (int i = 1; i <= N; i++) {
			if(inDegree[i] == 0) {
				pq.offer(i);
			}
		}
		
		// 위상 정렬 결과를 저장할 리스트
		List<Integer> result = new ArrayList<>();
		
		// 큐가 비어있지 않을 때까지 반복
		while(!pq.isEmpty()) {
			int current = pq.poll(); // 큐에서 문제 하나 꺼내기
			result.add(current); // 현재 문제를 결과 리스트에 추가
			
			// 현재 문제에 의존하는 문제(후행 문제)들에 대해
			for(int n:graph.get(current)) {
				inDegree[n]--; // 진입 차수 감소
				if(inDegree[n] == 0) { // 진입 차수가 0이 되면
					pq.offer(n); // 큐에 추가
				}
			}
		}

		for(int problem: result) {
			System.out.print(problem + " ");
		}
		
		sc.close();
	}

}
728x90
반응형

'LG 유플러스 유레카 SW > Algorithm' 카테고리의 다른 글

[#21] MST(최소신장트리) + 다익스트라 알고리즘  (1) 2025.02.24
[#20] 알고리즘 - 최단 경로  (0) 2025.02.21
[#19] 비선형 자료구조 - 그래프  (0) 2025.02.20
[#18] 비선형 자료구조 - 트리  (0) 2025.02.19
[#17] 순열 & 조합 & 부분집합  (0) 2025.02.18
  1. 백트래킹
  2. 위상 정렬(Topological Sorting)
'LG 유플러스 유레카 SW/Algorithm' 카테고리의 다른 글
  • [#21] MST(최소신장트리) + 다익스트라 알고리즘
  • [#20] 알고리즘 - 최단 경로
  • [#19] 비선형 자료구조 - 그래프
  • [#18] 비선형 자료구조 - 트리
nueos
nueos
  • nueos
    nueos 공부 기록
    nueos
  • 전체
    오늘
    어제
    • 분류 전체보기 (191)
      • 해커톤 (1)
      • 네이버 BoostCamp (6)
      • LG 유플러스 유레카 SW (3)
        • React (21)
        • TypeScript (2)
        • JavaScript (2)
        • HTML+CSS (5)
        • Spring (7)
        • Java (6)
        • SQL (2)
        • Algorithm (8)
        • CX (6)
        • Git (2)
        • 프로젝트 (2)
        • 스터디 (9)
        • 과제 (8)
        • 특강 (1)
      • React (3)
      • Next (0)
      • Javascript (2)
      • HTML (2)
      • CSS (9)
      • Algorithm (6)
      • Database (0)
      • OS (13)
      • C++ (24)
      • Python (1)
      • jQuery (1)
      • Django (1)
      • Git (1)
      • 개발 지식 (3)
      • 정보 보안 (22)
      • 포렌식 (1)
      • 암호 (2)
      • 기타 (4)
      • 패스트캠퍼스 FE 프로젝트십 (5)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    큐
    heap
    완전 탐색
    Stack
    디지털혁신
    디지랩챌린지
    exhaustive search
    제주지역혁신플랫폼지능형서비스사업단
    스택
    제주해커톤
    Queue
    기술로바꾸는세상
    힙
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.2
nueos
[#22] 백트래킹 + 위상 정렬
상단으로

티스토리툴바

단축키

내 블로그

내 블로그 - 관리자 홈 전환
Q
Q
새 글 쓰기
W
W

블로그 게시글

글 수정 (권한 있는 경우)
E
E
댓글 영역으로 이동
C
C

모든 영역

이 페이지의 URL 복사
S
S
맨 위로 이동
T
T
티스토리 홈 이동
H
H
단축키 안내
Shift + /
⇧ + /

* 단축키는 한글/영문 대소문자로 이용 가능하며, 티스토리 기본 도메인에서만 동작합니다.