백준 1525 퍼즐
본문 바로가기
알고리즘 모음집/알고리즘 (Algorithm)

백준 1525 퍼즐

by KyeongMin 2019. 7. 23.
728x90
반응형

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

불러오는 중입니다...

메모리도 정말 적게 주고 정말 난감한 문제입니다. 처음에 문제를 풀 때 재귀를 써서 해볼까 생각했는데

탈출 조건이 명확하지 않았습니다. 그 이유는 맞출 수 없는 퍼즐인 경우에 계속 깊어질 수 있다는 점이

생기게 되어 bfs를 이용해서 돌려야 하는데 재귀같이 이전의 맵을 저장 해서 돌리고 싶었는데 

그게 쉬운 것만은 아녔습니다. 

그래서 이용한 방법이 map() 함수와 string을 이용한 방법이었습니다.

map 함수에 대해서 간단히 설명드리자면 원소를 key와 value 쌍으로 저장을 하는 것으로

맵 자체를 key로 해서 체크를 간편하게 할 수 있습니다.

 

0을 9로 바꾸어 123456789라는 키값이 되었을 때 그 키값에 얼마나 저장되어있는지 출력하면 되는 것입니다.

3  * 3 이차원 배열을 이차원인 string으로 만들고 

find() 함수를 이용하여 현재 9의 위치 즉 0의 위치를 찾습니다.

그리고 여기서 

이렇게 한이유는 

맵이 저렇게 입력이 들어왔다면 이차원 배열을 129345678 string으로 만들면 

1은 0번의 인덱스를 9는 2의 인덱스를 가지게 됩니다.

find 함수를 이용하여 9의 인덱스를 알았고 2라는 인덱스를 이용하여

2차원 배열의 0,2라는 것을 알기 위해서

-> 행을 y라 했을 때  y는   find(9)의 위치 2에 / 3을 나누어 0을 가지게 하고

    열을 x라 했을 때 x는 find(9)%3으로 3으로 나눈 나머지인 2를 가지게 됨으로 

0,2에 있다는 것을 알 수 있습니다. 이런 식으로 계산하여 쓴 것입니다.

 

인덱스 계산은 하다 보면 이해가 되실 겁니다.

 

여기서 가장 큰 포인트는 맵을 이용 해 visit을 만들었는데

현재 나온 맵과 이전에 맵이 중복이 되지 않도록 count라는 컨테이너를 이용하여 같으면 1이 나오는데! 연산자로 

큐에 들어갈 수 없게 했습니다.

 

이렇게 count를 이용하여 된 배열이 완성된 123456789와 같이 완성된 적이 있는지 확인하여

없으면 -1

있으면 완성된 것으로 그 위치에 몇 번 만에 왔는지 저장되어있으므로 그 값을 출력하면 됩니다.

자세한 소스는 아래를 참고해주세요.  

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
#include<stdio.h>
#include<string>
#include<map>
#include<queue>
#include<algorithm>
using namespace std;
int dx[4= { 0,0,1,-1 };
int dy[4= { 1,-1,0,0 };
string s;
string e = "123456789";
queue<string> q;
map<stringint> visit;
void init() {
    for (int i = 0; i < 3; i++) {
        for (int j = 0; j < 3; j++) {
            char a;
            scanf(" %1c",&a);
            if (a == '0')a = '9';
            s.push_back(a);
        }
    }
}
int main(void) {
    init();
    q.push(s);
    visit[s] = 0;
    while (!q.empty()) {
        string c = q.front(); q.pop();
        if (c == e) {
            break;
        }
        int zero_pos = c.find('9');
        int y = zero_pos / 3;
        int x = zero_pos % 3;
        for (int d = 0; d < 4; d++) {
            int ny = y + dy[d];
            int nx = x + dx[d];
            if (0 <= ny && ny < 3 && 0 <= nx && nx < 3) {
                string t = c;
                swap(t[y * 3 + x], t[ny * 3 + nx]);// 갈수 있는 위치
                if (!visit.count(t)) {//한번 도 나온 경우가 아니라면
                    visit[t] = visit[c] + 1;
                    q.push(t);
                }
            }
        }
    }
    if (!visit.count(e)) {
        printf("-1\n");
    }
    else {
        printf("%d\n", visit[e]);
    }
    return 0;
}
 
 

728x90
반응형

'알고리즘 모음집 > 알고리즘 (Algorithm)' 카테고리의 다른 글

백준 10973 이전 순열  (0) 2019.07.23
백준 10972 다음 순열  (0) 2019.07.23
백준 10974 모든 순열  (0) 2019.07.23
백준 16137 견우와 직녀  (0) 2019.07.23
백준 2309 일곱 난쟁이  (0) 2019.07.21

댓글