코테/백준

[백준/JAVA] 21315번: 카드 섞기

imname1am 2024. 5. 28. 18:01
반응형

📖 문제

https://www.acmicpc.net/problem/21315

 

 

 

💡  풀이 방식

• 브루트포스

 

 

🔺 코드

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
import java.util.*;
import java.io.*;
 
public class Main {
    static int N, K, K1, K2;
    static int[] input, deck;
    
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st;
        
        N = Integer.parseInt(br.readLine());
        
        input = new int[N];
        deck = new int[N];
        
        st = new StringTokenizer(br.readLine(), " ");
        for(int i = 0 ; i < N ; i++) {
            input[i] = Integer.parseInt(st.nextToken());
            deck[i] = i+1;
        }
        
        for(int i = 1 ; Math.pow(2, i) < N ; i++) {
            for(int j = 1 ; Math.pow(2, j) < N ; j++) {
                int[] arr = deck.clone();
                
                shuffle(i, arr);
                shuffle(j, arr);
                
                boolean flag = true;
                for(int k = 0 ; k < N ; k++) {
                    if(arr[k] != input[k]) {
                        flag = false;
                        break;
                    }
                }
                
                if(flag) {
                    K1 = i;
                    K2 = j;
                    break;
                }
            }
        }
        
        System.out.println(K1 + " " + K2);
    }
    
    private static void shuffle(int k, int[] arr) {
        int range = N;
        int cnt = 0;
        
        for(int i = 1 ; i <= k+1 ; i++) {
            cnt = (int)Math.pow(2, k-i+1);
            swap(range, cnt, arr);
            range = cnt;
        }
    }
    
    private static void swap(int range, int cnt, int[] arr) {
        List<Integer> tmp = new ArrayList<>();
        
        // 2^k-i+1개 카드를 임시 배열에 넣기
        for(int i = range-cnt ; i < range ; i++) {
            tmp.add(arr[i]);
            arr[i] = 0// 배열에는 0 표시
        }
        
        // 임시 배열로 옮긴 원소들을 맨 위로 올리기
        for(int i = 0 ; i < N ; i++) {
            // 0이 아닌 부분은 임시 리스트 뒤에 넣기
            if(arr[i] != 0) {
                tmp.add(arr[i]);
            }
            // 해당 위치에 임시 배열의 같은 위치에 있는 원소 넣기
            arr[i] = tmp.get(i);
        }
    }
}
 
cs

 

 

➕ 다른 풀이 방식

개인적으로 이게 더 이해하기 쉬웠당,, (출처 : https://www.acmicpc.net/source/78306893)

LinkedList를 사용하심

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
import java.util.*;
import java.io.*;
 
public class Main {
    static int N;
    static int[] arr;
    static LinkedList<Integer> list;    // 변형된 리스트
    
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        
        N = Integer.parseInt(br.readLine());
        arr = new int[N];
        
        StringTokenizer st = new StringTokenizer(br.readLine(), " ");
        for(int i = 0 ; i < N ; i++) {
            arr[i] = Integer.parseInt(st.nextToken());
        }
        
        for(int i = 1 ; Math.pow(2, i) < N ; i++) {
            for(int j = 1 ; Math.pow(2, j) < N ; j++) {
                // 리스트에 1부터 N까지 숫자 추가
                list = new LinkedList<>();
                for(int x = 1 ; x <= N ; x++) {
                    list.add(x);
                }
                
                shuffle(i);    // i번 섞기
                shuffle(j);    // j번 섞기
                
                // 섞인 리스트가 주어진 배열과 같은지 확인
                if(chk()) {
                    System.out.println(i + " " + j);
                    return;
                }
            }
        }
    }
    
    // 리스트가 주어진 배열과 같은지 확인하는 함수
    private static boolean chk() {
        for(int i = 0 ; i < N ; i++) {
            if(arr[i] != list.get(i))
                return false;
        }
 
        return true;
    }
    
    // 리스트 섞는 함수
    private static void shuffle(int k) {
        int x = 1;    // 시작 인덱스
        
        // k번 반복
        while(k - x + 1 >= 0) {
            int cnt = (int)Math.pow(2, k-x+1);    // 2의 k-x+1 승
            
            // cnt번 반복
            for(int j = 0 ; j < cnt ; j++) {
                if(x == 1)    // 리스트의 마지막 요소를 첫 번째로 이동
                    list.addFirst(list.removeLast());
                else    // 2의 k-x+2 승 - 1 위치의 요소를 첫 번째로 이동
                    list.addFirst(list.remove((int)Math.pow(2, k-x+2-1));
            }
            
            x++;    // 인덱스 증가
        }
    }
}
 
cs
 

 

 


💦 어려웠던 점

- 원소를 스위칭하고 이걸 거꾸로??라는 생각에 차마 손을 대지 못 했다,,

 

🧐 새로 알게 된 내용

- ArrayList vs LinkedList의 차이. 삽입/삭제 시에는 LinkedList이 더 빠르다고 한다! (참고)

 

 

1회독 2회독 3회독 4회독 5회독
V        

(참고)

 

[백준] 21315 카드 섞기 java

문제 마술사 영재는 카드 더미를 이용한 마술을 개발하였다. 카드들에는 1부터 N까지의 숫자가 적혀있으며 초기 상태에는 1이 맨 위에 있으며 N개의 카드가 번호 순서대로 쌓여있다. 영재는 마술

kimensoo.tistory.com

 

반응형