// original: http://w...content-available-to-author-only...s.jp/m_hiroi/puzzle/eight.html
/*
* eigth1.c : 幅優先探索(双方向)
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#define TRUE 1
#define FALSE 0
#define FORWARD 1
#define BACKWARD 2
#define SIZE 9
#define NIL (-1)
/* 状態数 (9! / 2) */
#define MAX_STATE 181440
/* 隣接リスト */
const char adjacent[SIZE][5] = {
1, 3,-1,-1,-1,
0, 4, 2,-1,-1,
1, 5,-1,-1,-1,
0, 4, 6,-1,-1,
1, 3, 5, 7,-1,
2, 4, 8,-1,-1,
3, 7,-1,-1,-1,
4, 6, 8,-1,-1,
5, 7,-1,-1,-1,
};
/* キュー */
char state[MAX_STATE + 1][SIZE]; /* +1 はワーク領域 */
char space_position[MAX_STATE];
int prev_state[MAX_STATE];
int number_table[MAX_STATE];
/* 同一局面チェックテーブル */
char check_table[MAX_STATE * 2];
/* 初期状態 */
char init_state[SIZE] = {
8, 6, 7, 2, 5, 4, 3, 0, 1
};
/* 終了状態 */
char final_state[SIZE] = {
1, 2, 3, 4, 5, 6, 7, 8, 0
};
char dir[SIZE][SIZE] = {
/* 1 */ { '?', 'l', '?', 'u', '?', '?', '?', '?', '?' },
/* 2 */ { 'r', '?', 'l', '?', 'u', '?', '?', '?', '?' },
/* 3 */ { '?', 'r', '?', '?', '?', 'u', '?', '?', '?' },
/* 4 */ { 'd', '?', '?', '?', 'l', '?', 'u', '?', '?' },
/* 5 */ { '?', 'd', '?', 'r', '?', 'l', '?', 'u', '?' },
/* 6 */ { '?', '?', 'd', 'r', 'r', '?', '?', '?', 'u' },
/* 7 */ { '?', '?', '?', 'd', '?', '?', '?', 'l', '?' },
/* 8 */ { '?', '?', '?', '?', 'd', '?', 'r', '?', 'l' },
/* 9 */ { '?', '?', '?', '?', '?', 'd', '?', 'r', '?' },
};
/***** 解を表示 *****/
void print_state( int n )
{
static int last_zero;
int i;
#if 1
for( i = 0; i < SIZE; i++ ){
if (state[n][i] == 0) break;
}
if (n
> 0) putchar(dir
[last_zero
][i
]); last_zero = i;
#endif
#if 0
for( i = 0; i < SIZE; i++ ){
if( i
== 3 || i
== 6 ) printf("\n"); }
#endif
}
void print_answer_forward( int n )
{
if( n > 1 ) print_answer_forward( prev_state[n] );
print_state( n );
}
void print_answer_backward( int n )
{
do {
n = prev_state[n];
print_state( n );
} while( prev_state[n] != -1 );
}
void print_answer( int pos1, int num1, int num2 )
{
/* num2 の位置を見つける */
int pos2 = pos1 - 1;
while( num2 != number_table[pos2] ) pos2--;
if( check_table[num1] == FORWARD ){
print_answer_forward( pos1 );
print_answer_backward( pos2 );
} else {
print_answer_forward( pos2 );
print_answer_backward( pos1 );
}
}
/* 番号に変換 */
int change_number( char *board )
{
char work[SIZE];
static int fact_table[SIZE] = {
40320, 5040, 720, 120, 24, 6, 2, 1, 0,
};
int j, k, value = 0;
for( j = 0; j < SIZE - 1; j++ ){
value += fact_table[j] * work[j];
for( k = j + 1; k < SIZE; k++ ){
if( work[j] < work[k] ) work[k]--;
}
}
return value;
}
/* キューの初期化 */
void init_queue( void )
{
int num, i;
/* スタート */
memcpy( state
[0], init_state
, SIZE
); for (i = 0; i < SIZE; i++) {
if (init_state[i] == 0) space_position[0] = i;
}
prev_state[0] = -1;
num = change_number( init_state );
number_table[0] = num;
check_table[ num ] = FORWARD;
/* ゴール */
memcpy( state
[1], final_state
, SIZE
); space_position[1] = 8;
prev_state[1] = -1;
num = change_number( final_state );
number_table[1] = num;
check_table[ num ] = BACKWARD;
}
/* 探索 */
void search( void )
{
int front = 0, rear = 2;
/* 初期化 */
init_queue();
while( front < rear ){
int s = space_position[front];
int num1 = number_table[front];
int num2, i, n;
for( i = 0; (n = adjacent[s][i]) != -1; i++ ){
/* 状態をコピー */
memcpy( state
[rear
], state
[front
], SIZE
); /* 移動 */
state[rear][s] = state[rear][n];
state[rear][n] = 0;
space_position[rear] = n;
prev_state[rear] = front;
num2 = change_number( state[rear] );
if( !check_table[num2] ){
/* 登録 */
number_table[rear] = num2;
check_table[num2] = check_table[num1];
rear++;
} else if( check_table[num1] != check_table[num2] ){
/* 解が見つかった */
print_answer( rear, num1, num2 );
return;
}
}
front++;
}
}
int main(int argc, char *argv[])
{
int i;
if (argc
!= 2 || strlen(argv
[1]) != 9) { fprintf(stderr
, "Usage: %s 9numbers\n", argv
[0]); }
for (i = 0; i < 9; i++) {
int n = argv[1][i] - '0';
if (n < 0 || 8 < n) {
fprintf(stderr
, "invalid number: %c\n", argv
[1][i
]); }
init_state[i] = n;
}
search();
return 0;
}
Ly8gb3JpZ2luYWw6IGh0dHA6Ly93Li4uY29udGVudC1hdmFpbGFibGUtdG8tYXV0aG9yLW9ubHkuLi5zLmpwL21faGlyb2kvcHV6emxlL2VpZ2h0Lmh0bWwKLyoKICogZWlndGgxLmMgOiDluYXlhKrlhYjmjqLntKLvvIjlj4zmlrnlkJHvvIkKICoKICovCiNpbmNsdWRlIDxzdGRpby5oPgojaW5jbHVkZSA8c3RkbGliLmg+CiNpbmNsdWRlIDxzdHJpbmcuaD4KI2luY2x1ZGUgPHRpbWUuaD4KCiNkZWZpbmUgVFJVRSAgMQojZGVmaW5lIEZBTFNFIDAKI2RlZmluZSBGT1JXQVJEICAxCiNkZWZpbmUgQkFDS1dBUkQgMgojZGVmaW5lIFNJWkUgIDkKI2RlZmluZSBOSUwgICAoLTEpCgovKiDnirbmhYvmlbAgKDkhIC8gMikgKi8KI2RlZmluZSBNQVhfU1RBVEUgMTgxNDQwCgovKiDpmqPmjqXjg6rjgrnjg4ggKi8KY29uc3QgY2hhciBhZGphY2VudFtTSVpFXVs1XSA9IHsKICAxLCAzLC0xLC0xLC0xLAogIDAsIDQsIDIsLTEsLTEsCiAgMSwgNSwtMSwtMSwtMSwKICAwLCA0LCA2LC0xLC0xLAogIDEsIDMsIDUsIDcsLTEsCiAgMiwgNCwgOCwtMSwtMSwKICAzLCA3LC0xLC0xLC0xLAogIDQsIDYsIDgsLTEsLTEsCiAgNSwgNywtMSwtMSwtMSwKfTsKCi8qIOOCreODpeODvCAqLwpjaGFyIHN0YXRlW01BWF9TVEFURSArIDFdW1NJWkVdOyAgICAgIC8qICsxIOOBr+ODr+ODvOOCr+mgmOWfnyAqLwpjaGFyIHNwYWNlX3Bvc2l0aW9uW01BWF9TVEFURV07CmludCAgcHJldl9zdGF0ZVtNQVhfU1RBVEVdOwppbnQgIG51bWJlcl90YWJsZVtNQVhfU1RBVEVdOwoKLyog5ZCM5LiA5bGA6Z2i44OB44Kn44OD44Kv44OG44O844OW44OrICovCmNoYXIgY2hlY2tfdGFibGVbTUFYX1NUQVRFICogMl07CgovKiDliJ3mnJ/nirbmhYsgKi8KY2hhciBpbml0X3N0YXRlW1NJWkVdID0gewogIDgsIDYsIDcsIDIsIDUsIDQsIDMsIDAsIDEKfTsKCi8qIOe1guS6hueKtuaFiyAqLwpjaGFyIGZpbmFsX3N0YXRlW1NJWkVdID0gewogIDEsIDIsIDMsIDQsIDUsIDYsIDcsIDgsIDAKfTsKCmNoYXIgZGlyW1NJWkVdW1NJWkVdID0gewogIC8qIDEgKi8geyAnPycsICdsJywgJz8nLCAndScsICc/JywgJz8nLCAnPycsICc/JywgJz8nIH0sCiAgLyogMiAqLyB7ICdyJywgJz8nLCAnbCcsICc/JywgJ3UnLCAnPycsICc/JywgJz8nLCAnPycgfSwKICAvKiAzICovIHsgJz8nLCAncicsICc/JywgJz8nLCAnPycsICd1JywgJz8nLCAnPycsICc/JyB9LAogIC8qIDQgKi8geyAnZCcsICc/JywgJz8nLCAnPycsICdsJywgJz8nLCAndScsICc/JywgJz8nIH0sCiAgLyogNSAqLyB7ICc/JywgJ2QnLCAnPycsICdyJywgJz8nLCAnbCcsICc/JywgJ3UnLCAnPycgfSwKICAvKiA2ICovIHsgJz8nLCAnPycsICdkJywgJ3InLCAncicsICc/JywgJz8nLCAnPycsICd1JyB9LAogIC8qIDcgKi8geyAnPycsICc/JywgJz8nLCAnZCcsICc/JywgJz8nLCAnPycsICdsJywgJz8nIH0sCiAgLyogOCAqLyB7ICc/JywgJz8nLCAnPycsICc/JywgJ2QnLCAnPycsICdyJywgJz8nLCAnbCcgfSwKICAvKiA5ICovIHsgJz8nLCAnPycsICc/JywgJz8nLCAnPycsICdkJywgJz8nLCAncicsICc/JyB9LAp9OwoKLyoqKioqIOino+OCkuihqOekuiAgKioqKiovCnZvaWQgcHJpbnRfc3RhdGUoIGludCBuICkKewogIHN0YXRpYyBpbnQgbGFzdF96ZXJvOwogIGludCBpOwoKI2lmIDEKICBmb3IoIGkgPSAwOyBpIDwgU0laRTsgaSsrICl7CiAgICAgaWYgKHN0YXRlW25dW2ldID09IDApIGJyZWFrOwogIH0KICBpZiAobiA+IDApIHB1dGNoYXIoZGlyW2xhc3RfemVyb11baV0pOwogIGxhc3RfemVybyA9IGk7CiNlbmRpZgojaWYgMAogIHByaW50ZigiXG4iKTsKICBmb3IoIGkgPSAwOyBpIDwgU0laRTsgaSsrICl7CiAgICBpZiggaSA9PSAzIHx8IGkgPT0gNiApIHByaW50ZigiXG4iKTsKICAgIHByaW50ZigiJWQgIiwgc3RhdGVbbl1baV0gKTsKICB9CiAgcHJpbnRmKCJcblxuIik7CiNlbmRpZgp9Cgp2b2lkIHByaW50X2Fuc3dlcl9mb3J3YXJkKCBpbnQgbiApCnsKICBpZiggbiA+IDEgKSBwcmludF9hbnN3ZXJfZm9yd2FyZCggcHJldl9zdGF0ZVtuXSApOwogIHByaW50X3N0YXRlKCBuICk7Cn0KCnZvaWQgcHJpbnRfYW5zd2VyX2JhY2t3YXJkKCBpbnQgbiApCnsKICBkbyB7CiAgICBuID0gcHJldl9zdGF0ZVtuXTsKICAgIHByaW50X3N0YXRlKCBuICk7CiAgfSB3aGlsZSggcHJldl9zdGF0ZVtuXSAhPSAtMSApOwp9Cgp2b2lkIHByaW50X2Fuc3dlciggaW50IHBvczEsIGludCBudW0xLCBpbnQgbnVtMiApCnsKICAvKiBudW0yIOOBruS9jee9ruOCkuimi+OBpOOBkeOCiyAqLwogIGludCBwb3MyID0gcG9zMSAtIDE7CiAgd2hpbGUoIG51bTIgIT0gbnVtYmVyX3RhYmxlW3BvczJdICkgcG9zMi0tOwogIGlmKCBjaGVja190YWJsZVtudW0xXSA9PSBGT1JXQVJEICl7CiAgICBwcmludF9hbnN3ZXJfZm9yd2FyZCggcG9zMSApOwogICAgcHJpbnRfYW5zd2VyX2JhY2t3YXJkKCBwb3MyICk7CiAgfSBlbHNlIHsKICAgIHByaW50X2Fuc3dlcl9mb3J3YXJkKCBwb3MyICk7CiAgICBwcmludF9hbnN3ZXJfYmFja3dhcmQoIHBvczEgKTsKICB9CiAgcHV0Y2hhcignXG4nKTsKfQoKLyog55Wq5Y+344Gr5aSJ5o+bICovCmludCBjaGFuZ2VfbnVtYmVyKCBjaGFyICpib2FyZCApCnsKICBjaGFyIHdvcmtbU0laRV07CiAgc3RhdGljIGludCBmYWN0X3RhYmxlW1NJWkVdID0gewogICAgNDAzMjAsIDUwNDAsIDcyMCwgMTIwLCAyNCwgNiwgMiwgMSwgMCwKICB9OwogIGludCBqLCBrLCB2YWx1ZSA9IDA7CiAgbWVtY3B5KCB3b3JrLCBib2FyZCwgU0laRSApOwogIGZvciggaiA9IDA7IGogPCBTSVpFIC0gMTsgaisrICl7CiAgICB2YWx1ZSArPSBmYWN0X3RhYmxlW2pdICogd29ya1tqXTsKICAgIGZvciggayA9IGogKyAxOyBrIDwgU0laRTsgaysrICl7CiAgICAgIGlmKCB3b3JrW2pdIDwgd29ya1trXSApIHdvcmtba10tLTsKICAgIH0KICB9CiAgcmV0dXJuIHZhbHVlOwp9CgovKiDjgq3jg6Xjg7zjga7liJ3mnJ/ljJYgKi8Kdm9pZCBpbml0X3F1ZXVlKCB2b2lkICkKewogIGludCBudW0sIGk7CiAgLyog44K544K/44O844OIICovCiAgbWVtY3B5KCBzdGF0ZVswXSwgaW5pdF9zdGF0ZSwgU0laRSApOwogIGZvciAoaSA9IDA7IGkgPCBTSVpFOyBpKyspIHsKICAgICAgICBpZiAoaW5pdF9zdGF0ZVtpXSA9PSAwKSBzcGFjZV9wb3NpdGlvblswXSA9IGk7CiAgfQogIHByZXZfc3RhdGVbMF0gPSAtMTsKICBudW0gPSBjaGFuZ2VfbnVtYmVyKCBpbml0X3N0YXRlICk7CiAgbnVtYmVyX3RhYmxlWzBdID0gbnVtOwogIGNoZWNrX3RhYmxlWyBudW0gXSA9IEZPUldBUkQ7CiAgLyog44K044O844OrICovCiAgbWVtY3B5KCBzdGF0ZVsxXSwgZmluYWxfc3RhdGUsIFNJWkUgKTsKICBzcGFjZV9wb3NpdGlvblsxXSA9IDg7CiAgcHJldl9zdGF0ZVsxXSA9IC0xOwogIG51bSA9IGNoYW5nZV9udW1iZXIoIGZpbmFsX3N0YXRlICk7CiAgbnVtYmVyX3RhYmxlWzFdID0gbnVtOwogIGNoZWNrX3RhYmxlWyBudW0gXSA9IEJBQ0tXQVJEOwp9CgovKiDmjqLntKIgKi8Kdm9pZCBzZWFyY2goIHZvaWQgKQp7CiAgaW50IGZyb250ID0gMCwgcmVhciA9IDI7CiAgLyog5Yid5pyf5YyWICovCiAgaW5pdF9xdWV1ZSgpOwogIHdoaWxlKCBmcm9udCA8IHJlYXIgKXsKICAgIGludCBzID0gc3BhY2VfcG9zaXRpb25bZnJvbnRdOwogICAgaW50IG51bTEgPSBudW1iZXJfdGFibGVbZnJvbnRdOwogICAgaW50IG51bTIsIGksIG47CiAgICBmb3IoIGkgPSAwOyAobiA9IGFkamFjZW50W3NdW2ldKSAhPSAtMTsgaSsrICl7CiAgICAgIC8qIOeKtuaFi+OCkuOCs+ODlOODvCAqLwogICAgICBtZW1jcHkoIHN0YXRlW3JlYXJdLCBzdGF0ZVtmcm9udF0sIFNJWkUgKTsKICAgICAgLyog56e75YuVICovCiAgICAgIHN0YXRlW3JlYXJdW3NdID0gc3RhdGVbcmVhcl1bbl07CiAgICAgIHN0YXRlW3JlYXJdW25dID0gMDsKICAgICAgc3BhY2VfcG9zaXRpb25bcmVhcl0gPSBuOwogICAgICBwcmV2X3N0YXRlW3JlYXJdID0gZnJvbnQ7CiAgICAgIG51bTIgPSBjaGFuZ2VfbnVtYmVyKCBzdGF0ZVtyZWFyXSApOwogICAgICBpZiggIWNoZWNrX3RhYmxlW251bTJdICl7CiAgICAgICAgLyog55m76YyyICovCiAgICAgICAgbnVtYmVyX3RhYmxlW3JlYXJdID0gbnVtMjsKICAgICAgICBjaGVja190YWJsZVtudW0yXSA9IGNoZWNrX3RhYmxlW251bTFdOwogICAgICAgIHJlYXIrKzsKICAgICAgfSBlbHNlIGlmKCBjaGVja190YWJsZVtudW0xXSAhPSBjaGVja190YWJsZVtudW0yXSApewogICAgICAgIC8qIOino+OBjOimi+OBpOOBi+OBo+OBnyAqLwogICAgICAgIHByaW50X2Fuc3dlciggcmVhciwgbnVtMSwgbnVtMiApOwogICAgICAgIHJldHVybjsKICAgICAgfQogICAgfQogICAgZnJvbnQrKzsKICB9Cn0KCmludCBtYWluKGludCBhcmdjLCBjaGFyICphcmd2W10pCnsKICBpbnQgaTsKICBpZiAoYXJnYyAhPSAyIHx8IHN0cmxlbihhcmd2WzFdKSAhPSA5KSB7CiAgICBmcHJpbnRmKHN0ZGVyciwgIlVzYWdlOiAlcyA5bnVtYmVyc1xuIiwgYXJndlswXSk7CiAgICBleGl0KDEpOwogIH0KICBmb3IgKGkgPSAwOyBpIDwgOTsgaSsrKSB7CiAgICBpbnQgbiA9IGFyZ3ZbMV1baV0gLSAnMCc7CiAgICBpZiAobiA8IDAgfHwgOCA8IG4pIHsKICAgICAgZnByaW50ZihzdGRlcnIsICJpbnZhbGlkIG51bWJlcjogJWNcbiIsIGFyZ3ZbMV1baV0pOwogICAgICBleGl0KDEpOwogICAgfQogICAgaW5pdF9zdGF0ZVtpXSA9IG47CiAgfQogIHNlYXJjaCgpOwogIHJldHVybiAwOwp9