/*********************************/
/* 縦型探索(8パズル) */
/* coded by Y.Suganuma */
/*********************************/
import java.io.*;
import java.util.*;
class Depth
{
int dep;
String prev;
Depth (String str, int dep1)
{
prev = str; // 前の状態
dep = dep1; // 深さ
}
}
class Pair
{
String str;
int dep;
Pair (String str1, int dep1)
{
str = str1; // 状態
dep = dep1; // 深さ
}
}
class Search
{
/********************************/
/* コマの移動 */
/* str : 現在の状態 */
/* res : 移動後の状態 */
/* return : 移動後の状態数 */
/********************************/
int move(String str, String res[])
{
int k, n = 0;
String str1;
char c[] = new char [2];
k = str.indexOf('0');
switch(k) {
case 0:
c = str.substring(k+3,k+4).toCharArray();
str1 = str.replace('0', '9');
str1 = str1.replace(c[0],'0');
str1 = str1.replace('9', c[0]);
res[n] = str1;
n++;
c = str.substring(k+1,k+2).toCharArray();
str1 = str.replace('0', '9');
str1 = str1.replace(c[0],'0');
str1 = str1.replace('9', c[0]);
res[n] = str1;
n++;
break;
case 1:
c = str.substring(k+3,k+4).toCharArray();
str1 = str.replace('0', '9');
str1 = str1.replace(c[0],'0');
str1 = str1.replace('9', c[0]);
res[n] = str1;
n++;
c = str.substring(k-1,k).toCharArray();
str1 = str.replace('0', '9');
str1 = str1.replace(c[0],'0');
str1 = str1.replace('9', c[0]);
res[n] = str1;
n++;
c = str.substring(k+1,k+2).toCharArray();
str1 = str.replace('0', '9');
str1 = str1.replace(c[0],'0');
str1 = str1.replace('9', c[0]);
res[n] = str1;
n++;
break;
case 2:
c = str.substring(k+3,k+4).toCharArray();
str1 = str.replace('0', '9');
str1 = str1.replace(c[0],'0');
str1 = str1.replace('9', c[0]);
res[n] = str1;
n++;
c = str.substring(k-1,k).toCharArray();
str1 = str.replace('0', '9');
str1 = str1.replace(c[0],'0');
str1 = str1.replace('9', c[0]);
res[n] = str1;
n++;
break;
case 3:
c = str.substring(k-3,k-2).toCharArray();
str1 = str.replace('0', '9');
str1 = str1.replace(c[0],'0');
str1 = str1.replace('9', c[0]);
res[n] = str1;
n++;
c = str.substring(k+3,k+4).toCharArray();
str1 = str.replace('0', '9');
str1 = str1.replace(c[0],'0');
str1 = str1.replace('9', c[0]);
res[n] = str1;
n++;
c = str.substring(k+1,k+2).toCharArray();
str1 = str.replace('0', '9');
str1 = str1.replace(c[0],'0');
str1 = str1.replace('9', c[0]);
res[n] = str1;
n++;
break;
case 4:
c = str.substring(k-3,k-2).toCharArray();
str1 = str.replace('0', '9');
str1 = str1.replace(c[0],'0');
str1 = str1.replace('9', c[0]);
res[n] = str1;
n++;
c = str.substring(k+3,k+4).toCharArray();
str1 = str.replace('0', '9');
str1 = str1.replace(c[0],'0');
str1 = str1.replace('9', c[0]);
res[n] = str1;
n++;
c = str.substring(k-1,k).toCharArray();
str1 = str.replace('0', '9');
str1 = str1.replace(c[0],'0');
str1 = str1.replace('9', c[0]);
res[n] = str1;
n++;
c = str.substring(k+1,k+2).toCharArray();
str1 = str.replace('0', '9');
str1 = str1.replace(c[0],'0');
str1 = str1.replace('9', c[0]);
res[n] = str1;
n++;
break;
case 5:
c = str.substring(k-3,k-2).toCharArray();
str1 = str.replace('0', '9');
str1 = str1.replace(c[0],'0');
str1 = str1.replace('9', c[0]);
res[n] = str1;
n++;
c = str.substring(k+3,k+4).toCharArray();
str1 = str.replace('0', '9');
str1 = str1.replace(c[0],'0');
str1 = str1.replace('9', c[0]);
res[n] = str1;
n++;
c = str.substring(k-1,k).toCharArray();
str1 = str.replace('0', '9');
str1 = str1.replace(c[0],'0');
str1 = str1.replace('9', c[0]);
res[n] = str1;
n++;
break;
case 6:
c = str.substring(k-3,k-2).toCharArray();
str1 = str.replace('0', '9');
str1 = str1.replace(c[0],'0');
str1 = str1.replace('9', c[0]);
res[n] = str1;
n++;
c = str.substring(k+1,k+2).toCharArray();
str1 = str.replace('0', '9');
str1 = str1.replace(c[0],'0');
str1 = str1.replace('9', c[0]);
res[n] = str1;
n++;
break;
case 7:
c = str.substring(k-3,k-2).toCharArray();
str1 = str.replace('0', '9');
str1 = str1.replace(c[0],'0');
str1 = str1.replace('9', c[0]);
res[n] = str1;
n++;
c = str.substring(k-1,k).toCharArray();
str1 = str.replace('0', '9');
str1 = str1.replace(c[0],'0');
str1 = str1.replace('9', c[0]);
res[n] = str1;
n++;
c = str.substring(k+1,k+2).toCharArray();
str1 = str.replace('0', '9');
str1 = str1.replace(c[0],'0');
str1 = str1.replace('9', c[0]);
res[n] = str1;
n++;
break;
case 8:
c = str.substring(k-3,k-2).toCharArray();
str1 = str.replace('0', '9');
str1 = str1.replace(c[0],'0');
str1 = str1.replace('9', c[0]);
res[n] = str1;
n++;
c = str.substring(k-1,k).toCharArray();
str1 = str.replace('0', '9');
str1 = str1.replace(c[0],'0');
str1 = str1.replace('9', c[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;
char at[] = new char [10];
boolean sw;
String str = "", res[] = new String [4];
Pair pair;
Stack <Pair> s = new Stack <Pair> ();
TreeMap<String, Depth> m = new TreeMap<String, Depth> ();
m.put(start, new Depth("",dep));
s.add(new Pair(start, dep));
while (!s.isEmpty()) {
pair = s.pop();
str = pair.str;
dep = pair.dep;
node2++;
// ゴール
if (str.compareTo(goal) == 0) {
ct = dep;
break;
}
// ゴールでない
// コマを移動し,同じ状態のものがなければキューに追加
else {
if (dep < max) {
n = move(str, res);
for (i1 = 0; i1 < n; i1++) {
sw = true;
if (m.containsKey(res[i1])) {
if (dep+1 < m.ceilingEntry(res[i1]).getValue().dep)
m.remove(res[i1]);
else
sw = false;
}
if (sw) {
m.put(res[i1], new Depth(str,dep+1));
s.add(new Pair(res[i1], dep+1));
node1++;
}
}
}
}
}
// 結果の出力
System.out.printf(" 展開とチェック: %d %d, 最短距離: %d\n", node1, node2, ct);
while (str.length() > 0) {
at = str.toCharArray();
System.out.printf("\n %c %c %c\n", at[0], at[1], at[2]);
System.out.printf(" %c %c %c\n", at[3], at[4], at[5]);
System.out.printf(" %c %c %c\n", at[6], at[7], at[8]);
str = m.ceilingEntry(str).getValue().prev;
}
}
}
public class Test
{
public static void main (String[] args)
{
String goal = "123804765";
Search ss = new Search();
System.out.printf("例1\n");
String start = "283164705";
ss.depth(start, goal, 6);
System.out.printf("例2\n");
start = "216408753";
ss.depth(start, goal, 19);
}
}