BOJ_1525 : 퍼즐
문제
3×3 표에 다음과 같이 수가 채워져 있다. 오른쪽 아래 가장 끝 칸은 비어 있는 칸이다.
1 | 2 | 3 |
---|---|---|
4 | 5 | 6 |
7 | 8 |
어떤 수와 인접해 있는 네 개의 칸 중에 하나가 비어 있으면, 수를 그 칸으로 이동시킬 수가 있다. 물론 표 바깥으로 나가는 경우는 불가능하다. 우리의 목표는 초기 상태가 주어졌을 때, 최소의 이동으로 위와 같은 정리된 상태를 만드는 것이다. 다음의 예를 보자.
1 | 3 | |
---|---|---|
4 | 2 | 5 |
7 | 8 | 6 |
1 | 2 | 3 |
---|---|---|
4 | 5 | |
7 | 8 | 6 |
1 | 2 | 3 |
---|---|---|
4 | 5 | |
7 | 8 | 6 |
1 | 2 | 3 |
---|---|---|
4 | 5 | 6 |
7 | 8 |
가장 윗 상태에서 세 번의 이동을 통해 정리된 상태를 만들 수 있다. 이와 같이 최소 이동 횟수를 구하는 프로그램을 작성하시오.
입력
세 줄에 걸쳐서 표에 채워져 있는 아홉 개의 수가 주어진다. 한 줄에 세 개의 수가 주어지며, 빈 칸은 0으로 나타낸다.
출력
첫째 줄에 최소의 이동 횟수를 출력한다. 이동이 불가능한 경우 -1을 출력한다.
C++ 코드
#include <iostream>
#include <algorithm>
#include <map>
#include <queue>
#include <string>
using namespace std;
int dx[] = { 1, -1, 0, 0 };
int dy[] = { 0, 0, 1, -1 };
int main() {
/////////////입력//////////////
int n;
int start = 0;
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
cin >> n;
if (n == 0) n = 9; // 0은 몫,나머지를 못구함
start = start * 10 + n;
}
}
////////////map 구현/////////////
map<int, int> qube;
queue<int> q;
qube.insert(make_pair(start, 0));
q.push(start);
////////////bgs////////////////
while (!q.empty()) {
int now_num = q.front();
string now = to_string(now_num);
q.pop();
int z = now.find('9');
int x = z / 3; // 큐브에서 0의 x좌표
int y = z % 3; // 큐브에서 0의 y좌표
for (int k = 0; k < 4; k++) {
int nx = x + dx[k];
int ny = y + dy[k];
if (nx >= 0 && nx < 3 && ny >= 0 && ny < 3) {
string next = now;
swap(next[x * 3 + y], next[nx * 3 + ny]);
int num = stoi(next); //string to int
if (qube.count(num) == 0) {
qube[num] = qube[now_num] + 1; //큐브를 한번 움직임
q.push(num);
}
}
}
}
if (qube.count(123456789) == 0) cout << -1 << '\n';
else cout << qube[123456789] << '\n';
return 0;
}
Leave a comment