본문 바로가기
📊알고리즘/BOJ

[랜덤] BOJ 1091 - 카드 섞기

by meteorfish 2024. 10. 25.
728x90

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

 

아이디어: 10분

코딩: 15분 

접근법

카드를 석는 방법대로 카드의 위치를 옮기는 것이 핵심인 문제이다.

이는 직접 과정을 하나하나 하다보면 점화식을 구할 수 있다.

 

먼저 현재 카드를 before={0, 1, 2, 0, 1, 2}이고, 섞는 순서를 S={1 4 0 3 2 5}라고 가정해보자. 그리고 섞은 후의 배열을 after[]라고 하자. S를 0번부터 ~5번까지 돌면서 각 상황을 보자.

 

 

before의 S[0]번째 카드는 after의 0번으로 이동해야한다.

이를 식으로 표현하면 after[0] = before[S[0]]

 

before의 S[1]번째 카드는 after의 1번으로 이동해야한다.

이를 식으로 표현하면 after[1] = before[S[1]]

 

따라서, 섞는 순서를 반복문으로 표시하면 다음과 같이 표현할 수 있다.

for(int i=0;i<n;i++) {
     after[i] = before[s[i]];
}

 

시간 복잡도

문제의 경우, 카드가 48장 밖에 되지 않고 시간도 2초이므로 브루트포스로 풀어도 시간초과가 나지 않는다.

P가 될때까지 섞는 시간: O(N)

섞는 시간: O(N)

P가 되었는지 확인하는 시간: O(N)

총 O(N^3)에 문제를 해결할 수 있다.

 

코드

#include <iostream>
#include <cstring>
#include <algorithm>
#include <vector>
#include <map>
#include <cmath>
#include <queue>

#define ll long long

using namespace std;

int n;
int p[49];
int s[49];
int before[49];
int after[49];

bool check() {
    for(int i=0;i<n;i++) {
        if(before[i] != p[i])
            return false;
    }
    return true;
}

void init() {
    for(int i=0;i<n;i+=3) {
        for(int j=0;j<3;j++) {
            before[i+j] = j;
        }
    }
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    cout.tie(nullptr);

    cin >> n;
    for(int i=0;i<n;i++) {
        cin >> p[i];
    }
    for(int i=0;i<n;i++) {
        cin >> s[i];
    }

    init();

    int res = -1;
    for(int cnt =0;cnt<=1e7;cnt++) {
        if(check()) {
            res = cnt;
            break;
        }

        for(int i=0;i<n;i++) {
             after[i] = before[s[i]];
        }
        for(int i=0;i<n;i++) {
            before[i] = after[i];
        }
    }

    cout<<res;

    return 0;
}

 

728x90

'📊알고리즘 > BOJ' 카테고리의 다른 글

BOJ 1106 - 호텔  (0) 2024.10.29
BOJ 1034 - 램프  (0) 2024.10.28
[랜덤] BOJ 1011 - Fly me to the Alpha Centauri (C++)  (0) 2024.10.20
BOJ 27172 - 수 나누기 게임  (0) 2024.08.29
BOJ 2239 - 스도쿠  (0) 2024.08.27