본문 바로가기

알고리즘(Algorithm)

[C++] 부등호 (2529번)

부등호

 

문제

두 종류의 부등호 기호 ‘<’와 ‘>’가 k개 나열된 순서열 A가 있다. 우리는 이 부등호 기호 앞뒤에 서로 다른 한 자릿수 숫자를 넣어서 모든 부등호 관계를 만족시키려고 한다. 예를 들어, 제시된 부등호 순서열 A가 다음과 같다고 하자. 

A ⇒ < < < > < < > < >

부등호 기호 앞뒤에 넣을 수 있는 숫자는 0부터 9까지의 정수이며 선택된 숫자는 모두 달라야 한다. 아래는 부등호 순서열 A를 만족시키는 한 예이다. 

3 < 4 < 5 < 6 > 1 < 2 < 8 > 7 < 9 > 0

이 상황에서 부등호 기호를 제거한 뒤, 숫자를 모두 붙이면 하나의 수를 만들 수 있는데 이 수를 주어진 부등호 관계를 만족시키는 정수라고 한다. 그런데 주어진 부등호 관계를 만족하는 정수는 하나 이상 존재한다. 예를 들어 3456128790 뿐만 아니라 5689023174도 아래와 같이 부등호 관계 A를 만족시킨다. 

5 < 6 < 8 < 9 > 0 < 2 < 3 > 1 < 7 > 4

여러분은 제시된 k개의 부등호 순서를 만족하는 (k+1)자리의 정수 중에서 최댓값과 최솟값을 찾아야 한다. 앞서 설명한 대로 각 부등호의 앞뒤에 들어가는 숫자는 { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }중에서 선택해야 하며 선택된 숫자는 모두 달라야 한다

입력

첫 줄에 부등호 문자의 개수를 나타내는 정수 k가 주어진다. 그 다음 줄에는 k개의 부등호 기호가 하나의 공백을 두고 한 줄에 모두 제시된다. k의 범위는 2 ≤ k ≤ 9 이다. 

출력

여러분은 제시된 부등호 관계를 만족하는 k+1 자리의 최대, 최소 정수를 첫째 줄과 둘째 줄에 각각 출력해야 한다. 단 아래 예(1)과 같이 첫 자리가 0인 경우도 정수에 포함되어야 한다. 모든 입력에 답은 항상 존재하며 출력 정수는 하나의 문자열이 되도록 해야 한다. 


문제풀이

완전탐색 문제다. 백트래킹 기법도 들어가 있다.

1. 0~9 반복을 돌며 재귀 함수를 호출한다.

2. 재귀 함수에서는 부등호에 알맞은 숫자를 반복문을 돌며 뽑아낸다. 이때 방문했던 숫자는 재방문하지 않게 visit을 통해 관리한다.

3. 최대, 최솟값 저장

3. 부등호에 알맞지 않은 숫자는 자동으로 중간에 멈추니까 백트래킹!, 가능한 모든 방법을 찾아내니 브루트 포스!

 

#include <iostream>
#include <cmath>
#include <string>

using namespace std;

long long int max_ = 0, min_ = 9999999999;
int n;
char arr[9];
int visit[10];

// 현재 부등호(0번째부터), 답, 이전 숫자
void Dfs(int cnt, string answer, int before) {
	// 부등호 비교가 끝나면 최대 최소 확인 후 저장, 리턴
	if(cnt == n) {
		if(stoll(answer) > max_)
			max_ = stoll(answer);
		if(stoll(answer) < min_)
			min_ = stoll(answer);
		return;
	}
	
    // 방문 체크 (재사용 방지)
	visit[before] = 1;
	
    
	for(int i=0; i<=9; i++) {
		if(visit[i]) continue;
        // 부등호에 따른 처리
		if(arr[cnt] == '<' && before < i) {
			Dfs(cnt+1, answer+to_string(i), i);
		}
        // 부등호에 따른 처리
		else if(arr[cnt] == '>' && before > i) {
			Dfs(cnt+1, answer+to_string(i), i);
		}
	}
    // 둘다 포함안되면 백트래킹. 더이상 찾지 않음.
	
    // 해당 숫자 탐색 종료
	visit[before] = 0;
}

int main() {
	cin >> n;
	for(int i=0; i<n; i++)
		cin >> arr[i];
	
    // 첫번째 숫자 지정 0~9 반복
	for(int i=0; i<=9; i++)
		Dfs(0, to_string(i), i);
		
    // 정답이 long long int 이므로 만약 맨 앞이 0인 경우 처리 해줘야 함
	if(to_string(max_).size() != n+1)
		cout << "0" << max_ << "\n";
	else
		cout << max_ << "\n";
	
	if(to_string(min_).size() != n+1)
		cout << "0" << min_;
	else
		cout << min_;
		
	return 0;
}

 

'알고리즘(Algorithm)' 카테고리의 다른 글

[C++] 1, 2, 3 더하기 (9095번)  (0) 2022.11.01
[C++] DFS와 BFS (1260번)  (1) 2022.10.27
[C++] 주유소 (13305번)  (0) 2022.10.24
[C++] 부분수열의 합 (1182번)  (0) 2022.10.22
[C++] 프린터 큐 (1966번)  (0) 2022.10.20