縦型探索(8パズル)

/*********************************/
/* 縦型探索(8パズル)          */
/*           coded by Y.Suganuma */
/*********************************/
#include <stdio.h>
#include <stack>
#include <map>
#include <string>
using namespace std;

class Depth
{
	public:
		int dep;
		string prev;
		Depth (string str, int dep1)
		{
			prev = str;   // 前の状態
			dep  = dep1;   // 深さ
		}
};

/********************************/
/* コマの移動                   */
/*      str : 現在の状態        */
/*      res : 移動後の状態      */
/*      return : 移動後の状態数 */
/********************************/
int move(string str, string *res)
{
	int k, n = 0;
	string str1;

	k = str.find("0");
	switch(k) {
		case 0:
			str1   = str.replace(k, 1, str, k+3, 1);
			str1   = str1.replace(k+3, 1, 1, '0');
			res[n] = str1;
			n++;
			str1   = str.replace(k, 1, str, k+1, 1);
			str1   = str1.replace(k+1, 1, 1, '0');
			res[n] = str1;
			n++;
			break;
		case 1:
			str1   = str.replace(k, 1, str, k+3, 1);
			str1   = str1.replace(k+3, 1, 1, '0');
			res[n] = str1;
			n++;
			str1   = str.replace(k, 1, str, k-1, 1);
			str1   = str1.replace(k-1, 1, 1, '0');
			res[n] = str1;
			n++;
			str1   = str.replace(k, 1, str, k+1, 1);
			str1   = str1.replace(k+1, 1, 1, '0');
			res[n] = str1;
			n++;
			break;
		case 2:
			str1   = str.replace(k, 1, str, k+3, 1);
			str1   = str1.replace(k+3, 1, 1, '0');
			res[n] = str1;
			n++;
			str1   = str.replace(k, 1, str, k-1, 1);
			str1   = str1.replace(k-1, 1, 1, '0');
			res[n] = str1;
			n++;
			break;
		case 3:
			str1   = str.replace(k, 1, str, k-3, 1);
			str1   = str1.replace(k-3, 1, 1, '0');
			res[n] = str1;
			n++;
			str1   = str.replace(k, 1, str, k+3, 1);
			str1   = str1.replace(k+3, 1, 1, '0');
			res[n] = str1;
			n++;
			str1   = str.replace(k, 1, str, k+1, 1);
			str1   = str1.replace(k+1, 1, 1, '0');
			res[n] = str1;
			n++;
			break;
		case 4:
			str1   = str.replace(k, 1, str, k-3, 1);
			str1   = str1.replace(k-3, 1, 1, '0');
			res[n] = str1;
			n++;
			str1   = str.replace(k, 1, str, k+3, 1);
			str1   = str1.replace(k+3, 1, 1, '0');
			res[n] = str1;
			n++;
			str1   = str.replace(k, 1, str, k-1, 1);
			str1   = str1.replace(k-1, 1, 1, '0');
			res[n] = str1;
			n++;
			str1   = str.replace(k, 1, str, k+1, 1);
			str1   = str1.replace(k+1, 1, 1, '0');
			res[n] = str1;
			n++;
			break;
		case 5:
			str1   = str.replace(k, 1, str, k-3, 1);
			str1   = str1.replace(k-3, 1, 1, '0');
			res[n] = str1;
			n++;
			str1   = str.replace(k, 1, str, k+3, 1);
			str1   = str1.replace(k+3, 1, 1, '0');
			res[n] = str1;
			n++;
			str1   = str.replace(k, 1, str, k-1, 1);
			str1   = str1.replace(k-1, 1, 1, '0');
			res[n] = str1;
			n++;
			break;
		case 6:
			str1   = str.replace(k, 1, str, k-3, 1);
			str1   = str1.replace(k-3, 1, 1, '0');
			res[n] = str1;
			n++;
			str1   = str.replace(k, 1, str, k+1, 1);
			str1   = str1.replace(k+1, 1, 1, '0');
			res[n] = str1;
			n++;
			break;
		case 7:
			str1   = str.replace(k, 1, str, k-3, 1);
			str1   = str1.replace(k-3, 1, 1, '0');
			res[n] = str1;
			n++;
			str1   = str.replace(k, 1, str, k-1, 1);
			str1   = str1.replace(k-1, 1, 1, '0');
			res[n] = str1;
			n++;
			str1   = str.replace(k, 1, str, k+1, 1);
			str1   = str1.replace(k+1, 1, 1, '0');
			res[n] = str1;
			n++;
			break;
		case 8:
			str1   = str.replace(k, 1, str, k-3, 1);
			str1   = str1.replace(k-3, 1, 1, '0');
			res[n] = str1;
			n++;
			str1   = str.replace(k, 1, str, k-1, 1);
			str1   = str1.replace(k-1, 1, 1, '0');
			res[n] = str1;
			n++;
			break;
	}

	return n;
}

/*************************/
/* 縦型探索(8パズル)  */
/*      start : 初期状態 */
/*      goal : 目標状態  */
/*      max : 最大深さ   */
/*************************/
void depth(string start, string goal, int max)
{
	int i1, n, node1 = 1, node2 = 0, dep = 1, ct = 1;
	string str, res[4];
	stack<pair<string, int> > s;
	map<string, Depth> m;
	map<string, Depth>::iterator it;
	bool sw;

	m.insert(pair<string, Depth>(start, Depth("",dep)));
	s.push(pair<string, int>(start, dep));
	while (!s.empty()) {
		str = s.top().first;
		dep = s.top().second;
		node2++;
					// ゴール
		if (str == goal) {
			ct = dep;
			break;
		}
					// ゴールでない
					// コマを移動し,同じ状態のものがなければキューに追加
		else {
			s.pop();
			if (dep < max) {
				n = move(str, res);
				for (i1 = 0; i1 < n; i1++) {
					sw = true;
					it = m.find(res[i1]);   // 同じ状態か?
					if (it != m.end()) {
						if (dep+1 < ((*it).second).dep)
							m.erase(it);
						else
							sw = false;
					}
					if (sw) {
						m.insert(pair<string, Depth>(res[i1], Depth(str,dep+1)));
						s.push(pair<string, int>(res[i1], dep+1));
						node1++;
					}
				}
			}
		}
	}
					// 結果の出力
	printf("   展開とチェック: %d %d, 最短距離: %d\n", node1, node2, ct);
	while (str.length() > 0) {
		printf("\n      %c %c %c\n", str.at(0), str.at(1), str.at(2));
		printf("      %c %c %c\n", str.at(3), str.at(4), str.at(5));
		printf("      %c %c %c\n", str.at(6), str.at(7), str.at(8));
		it  = m.find(str);
		str = ((*it).second).prev;
	}
}

int main()
{
	string goal = "123804765";

	printf("例1\n");
	string start = "283164705";
	depth(start, goal, 6);

	printf("例2\n");
	start = "216408753";
	depth(start, goal, 19);

	return 0;
}