inflearn logo
강의

강의

N
챌린지

챌린지

멘토링

멘토링

N
클립

클립

로드맵

로드맵

지식공유

10주완성 C++ 코딩테스트 | 알고리즘 코딩테스트

3-M

3-M 순열 재귀, next_permutation

438

sol4854

작성한 질문수 17

0

안녕하세요 큰돌님!

문제를 보고 괄호추가하기와 같은 패턴으로 풀면 될것같아서 풀어보았습니다.

 

재귀를 사용해서 순열을 만들어 풀이한것이 통과가 되어서 next_permutation으로 만들어봤습니다.

 

그런데 생각대로 잘 되지가 않네요...ㅠㅜ

next_permutation으로 풀려면 어떤 방식으로 접근해야할까요??

 

좋은 강의 해주셔서 감사합니다:)

http://boj.kr/dd36ea0097404bbf8cdb802ca843eacd

c++ 코딩-테스트

답변 1

0

큰돌

안녕하세요 sol님 ㅎㅎ

좋은 발상인데요.

do while 괜찮은 거 같지만 이거는 별로인 거 같습니다.

예를 들어

9
> < < < > > > < <

이 예제 같은 경우는

그렇게 해도 됩니다.

그런 경우 코드는 다음과 같이 됩니다.

#include <iostream>
#include <algorithm>
#include <vector>
#include <string>
#include <numeric>

using namespace std;
int K,ret;
string ret_min = "9999999999", ret_max = "0000000000";
int nums[10];
string s;
vector<char> v;
vector<int> tmp, v_max, v_min, v_per;
bool check(char ch, int a, int b){
	if(ch == '<') {
		if(a < b) {
			return true;
		}
	}
	else if(ch == '>') {
		if(a > b) {
			return true;
		}
	}
	return false;
}
 
void n_per(){
	do{	  
		bool flag = true;
		for(int i = 0; i < K; i++){
			if(!check(v[i], v_per[i], v_per[i + 1])) flag = false;
		} 
		if(flag){ 
			string ret = "";
			for(int a : v_per){
				ret += a + '0';
			}  
			ret_max = max(ret_max,ret);
			ret_min = min(ret_min,ret); 
		}

	}while(next_permutation(v_per.begin(), v_per.end()));
}

int main(){
	ios_base::sync_with_stdio(false); cin.tie(NULL); cout.tie(NULL);

	cin >> K;

	for(int i = 0; i < K; i++){
		char tmp; cin >> tmp;
		v.push_back(tmp);
	} 
	for(int i = 0; i <= 9; i++) v_per.push_back(i);
	n_per();
	cout << ret_max << '\n';
	cout << ret_min << '\n'; 
}

어차피 같은 자릿수 비교이기 때문에 string으로 하는게 더 편해서 string으로 한점 등을 봐주세요.

 

다만, 이게 9가 아니면 문제가 있는데요.

예를 들어 2라고 했을 때

a b c

이 자리에 숫자가 들어가는데

a는 0 ~ 9

b는 0 ~ 9 중 한개뺀

...

이런 식으로 숫자가 들어가죠?

 

근데 이걸 do while로 하기에는 비효율적입니다.

do while을 기반으로 vector의 순서를 바꾸는 것뿐인데 이걸 기반으로 한다면 0 ~ 9를 집어넣고 K + 1을 slice해서 구현해야 합니다.

다음과 같이 말이죠.

#include <iostream>
#include <algorithm>
#include <vector>
#include <string>
#include <numeric>

using namespace std;
int K,ret;
string ret_min, ret_max;
int nums[10];
string s;
vector<char> v;
vector<int> tmp, v_max, v_min, v_per;
bool check(char ch, int a, int b){
	if(ch == '<') {
		if(a < b) {
			return true;
		}
	}
	else if(ch == '>') {
		if(a > b) {
			return true;
		}
	}
	return false;
}
 
void n_per(){
	do{	  
		bool flag = true;
		for(int i = 0; i < K; i++){
			if(!check(v[i], v_per[i], v_per[i + 1])) flag = false;
		} 
		if(flag){ 
			string ret = ""; 
			for(int i = 0; i < K + 1; i++) ret += v_per[i] + '0'; 
			ret_max = max(ret_max,ret);
			ret_min = min(ret_min,ret); 
		}

	}while(next_permutation(v_per.begin(), v_per.end()));
}

int main(){
	ios_base::sync_with_stdio(false); cin.tie(NULL); cout.tie(NULL);

	cin >> K;

	for(int i = 0; i < K; i++){
		char tmp; cin >> tmp;
		v.push_back(tmp);
	} 
	for(int i = 0; i <= 9; i++) v_per.push_back(i);
	for(int i = 0; i < K + 1; i++) ret_min += '9';
	for(int i = 0; i < K + 1; i++) ret_max += '0'; 
	
	n_per();
	cout << ret_max << '\n';
	cout << ret_min << '\n'; 
}

앞의 코드와 같이 구축하고 제출해보면 맞았다고는 뜨나 출력해보면 알겠지만 012 012 ... 이런식으로 반복되는 경우의 수가 생깁니다. (012345 012435.. 이런 경우의 수중에서 앞의 3개를 SLICE하게 되니..)

 

방금 제출해본 모습입니다. 재귀보다 DO WHILE이 56ms로 약 5배정도 느린 모습을 볼 수 있습니다.

image
또 질문 있으시면 언제든지 질문 부탁드립니다.

좋은 수강평과 별점 5점은 제가 큰 힘이 됩니다. :)

감사합니다.

강사 큰돌 올림.

0

sol4854

너무 친절한 답변 감사드립니다!

큰돌님 덕분에 즐겁게 알고리즘 공부하고있습니다ㅎㅎ

순열을 구할때 재귀, next_permutaion을 상황에 맞게 잘 구현해서 사용하겠습니다!

감사합니다!!

5-B

0

16

2

4 - A

0

33

2

코딩살구클럽 입장이 안됩니다

0

82

2

4-F 경우의 수 질문입니다.

0

35

2

코딩살구클럽 가입이 안됩니다.

0

85

2

살구 클럽에 대한 질문있습ㄴ디ㅏ

0

63

1

교안 158페이지 문의드립니다

0

47

2

코딩살구클럽 관련 건의사항

0

119

1

코살에 19942 다이어트 문제에 N의 범위가 빠져있슴니다

0

45

1

진행 방법 질문드립니다!

0

83

2

2-I) 왜 이 문제가 그래프이론 카테고리에 있는지 잘 모르겠습니다.

0

64

2

2주차 개념#12 트리 순회

0

33

2

백준사이트가 종료된다고 합니다.

0

318

2

백준 서비스 종료

9

953

1

sk 하이닉스 코테 대비

0

388

2

3-G 최댓값 질문

0

54

1

모듈러 연산 값이 10이 아닌 경우도 있지 않나요?

0

84

2

3-I 코드 질문드립니다.

0

66

2

3-N 질문 있습니다.

0

68

2

학습방법

0

105

2

4-H 질문 있습니다 (코드 리뷰)

0

69

2

코딩테스트 어디까지 준비해야 하는지 질문이 있습니다.

0

186

2

2-O 반례가 무엇일지 어떤 부분이 틀렸는지 잘 모르겠습니다.

0

74

2

2주차 개념 #4-2. 인접행렬 질문있습니다.

0

66

2