BOJ_1525 : 퍼즐

1 minute read

문제

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;

}

Updated:

Leave a comment