
https://www.acmicpc.net/problem/2529
2529번: 부등호
여러분은 제시된 부등호 관계를 만족하는 k+1 자리의 최대, 최소 정수를 첫째 줄과 둘째 줄에 각각 출력해야 한다. 단 아래 예(1)과 같이 첫 자리가 0인 경우도 정수에 포함되어야 한다. 모든 입력
www.acmicpc.net
문제
문제를 본 순간 순열을 사용하면 풀릴것 같다는 생각이 들었다.
K는 최대 9까지 나올 수 있으니
9! = 362880 임으로 1억이 안되는 걸로 보아 1초안에 테스트가 가능할 것이라고 생각했다.
또한 순열 로직안에서 1중 for문임으로 362880 x 9 = 3625920 널널하다!
내가 푼 로직은 이렇다.
1. K + 1 크기의 0~9까지의 수를 순열로 구한다.
2. 순열을 부등호와 비교하여 가능한지 체크
3. 만약 가능하다면 Min, Max를 비교하고 값을 String 형태로 저장후 출력.
아래는 K + 1 크기의 0~9 까지의 수로 만든 순열 기본 코드이다.
static void permutation(int count) {
if(count == K + 1) {
System.out.println(Arrays.toString(numbers));
return;
}
for(int i = 0; i < 10; i++) {
if(visit[i]) continue;
numbers[count] = i;
visit[i] = true;
permutation(count + 1);
visit[i] = false;
}
}
순열이 제대로 동작하는 것을 알 수 있었고, 여기서 단순 구현인 2번로직과 3번로직을 추가해주면 끝이다.
전체 코드
public class Main {
static int K;
static long min, max;
static String strMin, strMax;
static String[] split;
static int[] numbers;
static boolean[] visit;
public static void main(String[] args) throws Exception {
System.setIn(new FileInputStream("input.txt"));
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
StringBuilder sb = new StringBuilder();
StringTokenizer st;
K = Integer.parseInt(in.readLine());
split = in.readLine().split(" ");
visit = new boolean[10];
numbers = new int[K + 1];
min = Long.MAX_VALUE;
max = Long.MIN_VALUE;
// 수열문제.
permutation(0);
System.out.println(strMax);
System.out.println(strMin);
}
static void permutation(int count) {
if(count == K + 1) {
// 부등호와 매칭이 된다면 아래 로직을 실행.
if(isMatch()) {
String strNumber = getNumber();
long number = Long.parseLong(strNumber);
if(min > number) {
min = number;
strMin = strNumber;
}
if(max < number) {
max = number;
strMax = strNumber;
}
}
return;
}
for(int i = 0; i < 10; i++) {
if(visit[i]) continue;
numbers[count] = i;
visit[i] = true;
permutation(count + 1);
visit[i] = false;
}
}
static boolean isMatch() {
for(int i = 0; i < split.length; i++) {
String arrow = split[i];
if(arrow.equals(">")) {
if(numbers[i] <= numbers[i + 1]) {
return false;
}
}
else {
if(numbers[i] >= numbers[i + 1]) {
return false;
}
}
}
return true;
}
// int 배열을 문자열로 변경해주는 메소드.
static String getNumber() {
String number = "";
for(int i = 0; i < numbers.length; i++) {
number += Integer.toString(numbers[i]);
}
return number;
}
}
결과
풀고 난뒤 다른 사람의 풀이를 보니 순열이 아닌 백트레킹 자체로 푸신분들이 많았다.
순열을 구하고 비교하는 것이아니라 백트레킹이후 그때마다 부등호가 맞는지 체크한다면 가지치기가 가능할 것이라고 생각했고 이는 속도와 연결될 것이라고 생각한다.
'Algorism > 백준' 카테고리의 다른 글
[백준] 11048번 : 이동하기- JAVA [자바] (1) | 2024.01.03 |
---|---|
[백준] 5014번 : 스타트링크 - JAVA [자바] (1) | 2024.01.02 |
[백준] 14225번 : 부분수열의 합 - JAVA [자바] (1) | 2024.01.02 |
[백준] 15661번 : 링크와 스타트 - JAVA [자바] (0) | 2024.01.02 |
[백준] 14889번 : 스타트와 링크 - JAVA [자바] (1) | 2024.01.01 |