문제
집합의 순열이란 집합의 서로 다른 원소를 모두 사용해 만들 수 있는 순서이다. 예를 들어, {2,3,5}의 순열은 다음과 같다.
- 2 3 5
- 2 5 3
- 3 2 5
- 3 5 2
- 5 2 3
- 5 3 2
각각의 순열은 숫자로 나타낼 수 있다. 위의 순열은 사전순으로 쓰여져 있으며, 등장하는 순서를 이용해 나타낸다. 즉, 3 5 2는 위치 4에 있고, 5 3 2는 마지막 위치인 6에 있다.
{b,e,i,n}으로 만들 수 있는 순열은 다음과 같다.
- b e i n
- b e n i
- b i e n
- b i n e
- b n e i
- b n i e
- e b i n
- e b n i
- e i b n
- e i n b
- e n b i
- e n i b
- i b e n
- i b n e
- i e b n
- i e n b
- i n b e
- i n e b
- n b e i
- n b i e
- n e b i
- n e i b
- n i b e
- n i e b
서로 다른 숫자와 문자로 이루어진 집합과 위치가 주어졌을 때, 그 집합의 순열 중 주어진 위치의 순열을 구하는 프로그램을 작성하시오.
입력
입력은 여러 개의 테스트 케이스로 이루어져 있다. 각 테스트 케이스는 한 줄로 이루어져 있다. 첫 번째 문자열은 서로 다른 숫자와 알파벳으로 이루어져 있으며, 길이는 최대 10이다. 또한, 사전순 순서대로 주어진다. 문자열 다음에는 찾아야 하는 위치가 주어지며, 이 값은 3,628,800보다 작거나 같은 자연수이다.
출력
각각의 테스트 케이스마다, 입력으로 주어진 위치에 해당하는 순열을 공백없이 출력한다. 만약, 해당하는 순열이 없는 경우에는 "No permutation"을 출력한다.
예제 입력 1
235 4
bein 20
123456 700
mnpqr 130
tuvwxyz 4000
예제 출력 1
235 4 = 352
bein 20 = nbie
123456 700 = 651342
mnpqr 130 = No permutation
tuvwxyz 4000 = ywuxvzt
코드
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.StringTokenizer;
public class Main {
private static boolean[] visited;
private static int n,ans,flag;
private static char[] word;
private static char[] arr;
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String input = "";
while((input=br.readLine())!=null ) {
StringTokenizer st = new StringTokenizer(input);
if(!st.hasMoreTokens()) break;
word = st.nextToken().toCharArray();
n = Integer.parseInt(st.nextToken());
visited = new boolean[word.length];
ans = 0;
flag = 0;
arr = new char[word.length];
permutation(0);
if(flag == 0) {
System.out.print(word);
System.out.print(" "+ n+" = ");
System.out.println("No permutation");
}
}
}
static void permutation(int cnt) {
if(cnt == word.length) {
ans++;
if(ans == n) {
flag = 1;
System.out.print(word);
System.out.print(" "+ n+" = ");
System.out.println(arr);
return;
}
}
for (int i = 0; i < word.length; i++) {
if(!visited[i]) {
visited[i] = true;
arr[cnt] = word[i];
permutation(cnt+1);
visited[i] = false;
}
}
}
}
풀이
재귀를 이용하여 arr의 길이가 주어진 문자열의 길이가 될 때까지 아직 방문하지 않은 문자를 arr에 더해준다.
arr의 길이가 문자열의 길이와 같아지면 count를 증가시키고 이 값이 n과 같으면 이때의 arr를 출력해주고 flag값을 1로 바꾼 뒤 return을 해준다.
모든 경우의 수를 확인한 후에도 count 값이 n과 같아지지 않았다면 flag 값이 0으로 남아있을 것이다. 이 경우 No permutation을 출력한다.
'알고리즘 > 백트래킹' 카테고리의 다른 글
[백준][Python] 1759번 암호 만들기 (0) | 2022.12.02 |
---|---|
[백준][Python] 18429번 근손실 (0) | 2022.08.08 |
[백준][Python] 10974번 모든 순열 (0) | 2022.08.04 |
[백준][Python] 1182번 부분수열의 합 (0) | 2022.08.03 |
[백준][Python] 15652번 N과 M (4) (0) | 2022.08.01 |
댓글