Algorithm - Exhaustive search (완전탐색)

2025. 8. 26. 21:16·C++ 프로그래머스/Exhaustive search

완전탐색(Exhaustive search)이란?

컴퓨터의 계산능력을 이용하여 경우의 수를 모두 나열하면서 답을 찾는법을 뜻한다

예시로 자물쇠 4자리를 풀때 0000부터 9999까지 10000가지의 수를 모두 무식하게 다

나열하면서 푸는 방식을 뜻한다

 

"무식하게 다 계산하여 푼다"의 의미인 Brute-Force(브루트 포스) 라고 도 부른다

 

완전탐색을 써야할때는

 

경우의 수가 작을때 (입력으로 주어지는 데이터N의 크기가 매우 작을 때 )

문제 조건이 명확하게 모든 경우중 최적값을 찾아라 일때

구현이 쉽고 효율보다는 정확해야할경우

 

완전탐색 그 자체가 알고리즘은 아니고 문제 해결 방법이기때문에

완전 탐색 방법을 이용하기 위해서는 여러가지 알고리즘 기법이 사용됩니다

완전 탐색 기법
단순 Brute-Force
비트마스크(BitMask)
재귀함수
순열
BFS / DFS

 

단순 Brute-Force

아이디어, 최적화를 계산하지않고 가능한 모든 경우의 수를 다 시도해보는

모든 경우의 수를 하나하나 다 검사하여 맞는 답을 찾는것을 뜻한다

보통 for문과 if문으로 모든 case로 구현하여 답을 구한다

 

비트마스크 (Bit Mask)

정수의 이진수 표현을 사용하여 집합 을 0과 1로 표현하여

부분집합을 효율적으로 탐색할 수있게 해주는 방법이다

원소가 { 1, 2, 4, 5 } 가 있다고 해보자

해당 원소로 만들수있는 최대의 가짓수는 2^4 즉 16개이다

 

{1, 2, 4, 5}

Mask(진수) 2진수
0000 {}
0001 {1}
0010 {2}
0011 {1,2}
0101 {1,4}
0110 {2,4}
... ...
1111 {1,2,4,5}

 

나올수있는걸 2진수로 변환해서 나올수있는 가짓수를 다 계산한다 방식이다

이와같이 표현할수있다

#include <iostream>
#include <vector>
using namespace std;

int main()
{
	vector<int> arr = { 1, 2, 4, 5 };
	//mask를 0 부터 2^arr.size() - 1 까지 돌리기
	// 2^4는 16임 15까지만 돌아야함
	//즉 0 부터 15까지만 돌도록 
	
	//시프트 연산자를 사용하여 왼쪽으로 n비트 이동
	for (int mask = 0; mask < (1 << arr.size()); mask++)
	{
		cout << " { ";
		for (int i = 0; i < arr.size(); i++)
		{
			//mask에서 i번쨰 비트가 켜져있다면
			if (mask & (1 << i))
			{
				cout << arr[i] << " ";
			}
		}
		cout << " } " << endl;
	}
}

 

재귀 함수

문제를 만족하는 경우들을 만들어가는 방식이다

만들고자 하는 부분집합을 A 라고 할때 A = { } 부터 시작해서 원소에 대해서

원소가 조건에 만족이 된다면 A 에 넣고 재귀함수를 돌리고 조건이 만족이 안된다면

A를 그대로 재귀 함수에 넣어주는 방식

 

사용방식

#include <iostream>
#include <vector>
using namespace std;

//arr = 원소들, nowIndex = 현재인덱스, lastIndex = 마지막 인덱스
void permute(vector<int>& arr, int nowIndex, int lastIndex)
{
	//재귀 종료 조건 : 현재 인덱스가 마지막 인덱스면 순열 완성 
	if (nowIndex == lastIndex)
	{
		for (int x : arr)
		{
			//완성된 순열을 출력해라
			cout << x << " ";
		}
		cout << endl;
		return; //재귀 종료
	}

	//현재 인덱스부터 마지막 인덱스까지 반복
	//각 원소를 현재 위치에 놓고 재귀 호출
	for (int i = nowIndex; i <= lastIndex; i++)
	{
		//현재 인덱스와 i번째 원소 교환 , 현재 인덱스에 i번째 원소를 놓기위해 교환
		swap(arr[nowIndex], arr[i]);
		//다음 자리 재귀 호출 , 다음자리를 재귀적으로 채우기
		//주어진 배열의 모든 순열을 생성
		permute(arr, nowIndex + 1, lastIndex);
		//원새 상태로 복원 (backtracking)
		swap(arr[nowIndex], arr[i]);
	}
}
int main()
{
	vector<int> arr = { 1, 2, 5, 4 };
	permute(arr, 0, arr.size() - 1);
}

 

 

 

 

 

----

 

순열

(선택 순서가 결과에 영향을 미치는 경우)

 

C++에서는 next_permutation 라는 함수를 사용하여 재귀함수를 구현할수있다

 

필요한헤더

#include <algorithm>

 

사용방법

 

최소 한번은 실행하고 그 뒤에 조건을 검사해서 반복 여부를 결정하는 do-while문을 사용하면된다

for-while문으로 쓰면 첫 배열 상태는 출력이 안되지만 do-while으로 쓰면

첫배열부터 출력하여 간결하게 사용가능하다

#include <iostream>
#include <vector>
#include <algorithm> // next_permutation
using namespace std;

int main() 
{
	vector<int> arr = { 1, 2, 5, 4 };
	sort(arr.begin(), arr.end());

	do {
		for (int x : arr)
		{
			cout << x << " ";
		}
		cout << endl;
		//next_permutation은 오름차순으로 시작해야만함
	} while (next_permutation(arr.begin(), arr.end()));
}

 

DFS / BFS

 

DFS : Depth First Search (깊이 우선 탐색)

구현방식 : 재귀함수 / 스택

동작방식 : 해당 Branch를 모두 탐색한 이후에 다음 Branch로 이동하는 방식

즉 한경로를 끝까지 탐색한후 다른 경로를 탐색하는 방식

노드 방문시 방문 여부를 검사하지않으면 무한 루프에 빠질수 있음

 

시간복잡도 : 인접리스트로 구현시 O(V+E), 인접 행렬로 구현시 O(V^2)

장점 : 목표노드가 깊을때 값을 빨리 구할수 있다

단점 : 구현시 DFS를 재귀적으로 구현할때 재귀호출이 너무 깊어지면 스택오버플로우가 발생할수있음

재귀 깊이를 너무 깊어지지않도록 해야함

 

 

BFS : Breadth-First Search(너비 우선 탐색)

구현방식 : 큐

동작방식 : 모든 인접노드를 탐색한뒤 그다음 레벨로 이동하는 방식

즉 시작노드를 기준으로 가까운 노드를 먼저 방문

 

장점 : 발견한 경로가 최단 경로

단점 : 경로가 길어지면 많은 메모리 공간을 필요로 한다

 

시간복잡도 : O(V+E)

 

'C++ 프로그래머스 > Exhaustive search' 카테고리의 다른 글

프로그래머스(C++) - 최소 직사각형  (0) 2025.08.29
프로그래머스(C++) - 피로도  (0) 2025.08.29
프로그래머스(C++) - 카펫  (0) 2025.08.29
프로그래머스(C++) - 소수 찾기  (0) 2025.08.26
'C++ 프로그래머스/Exhaustive search' 카테고리의 다른 글
  • 프로그래머스(C++) - 최소 직사각형
  • 프로그래머스(C++) - 피로도
  • 프로그래머스(C++) - 카펫
  • 프로그래머스(C++) - 소수 찾기
lucodev
lucodev
언리얼 포폴개발 일기
  • lucodev
    루코 개발테이블
    lucodev
  • 전체
    오늘
    어제
    • 분류 전체보기 (213) N
      • Unreal 프로젝트 다이어리 (110) N
        • 첫번째 프로젝트 (73)
        • 두번째 프로젝트 (37) N
      • Unreal 팁 (8)
      • Unreal 디버깅 (8)
      • C++ 프로그래머스 (52)
        • Stack,Queue (7)
        • Hash (4)
        • Heap (2)
        • Sort (5)
        • Exhaustive search (5)
        • Greedy (2)
        • BFS , DFS (7)
        • Graph (2)
        • Dynamic Programming (1)
        • C++ Math (2)
        • 기타 문제 (14)
      • C++ 백준 (4)
      • C++ 팁 (1)
      • 개인 코테 & 스타디 <비공개> (29)
        • 코드 개인보관함 (9)
        • 코딩테스트+@ (11)
        • 알고리즘 스타디 (6)
        • 알고리즘 스타디 과제 (3)
        • 비공개 (0)
  • 인기 글

  • 최근 글

  • 최근 댓글

  • 링크

  • 공지사항

  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 태그

    언리얼 파쿠르
    언리얼 시퀀스
    Unreal Parkour
    언리얼 motionmatching
    언리얼 behaviortree
    unreal
    언리얼 인벤토리
    unreal 모션매칭
    언리얼
    unreal 인벤토리
    언리얼 컷씬
    unreal 파쿠르
    unreal inventory
    언리얼 프로그래스바
    언리얼 비헤이비어트리
    언리얼 모션매칭
    언리얼 parkour
    unreal 시퀀스
    언리얼 behavior tree
    언리얼 ui
  • hELLO· Designed By정상우.v4.10.3
lucodev
Algorithm - Exhaustive search (완전탐색)
상단으로

티스토리툴바