Problem:
MathJax.Hub.Config({ tex2jax: { inlineMath: [["$","$"], ["\\(","\\)"]], processEscapes: true }});

8 Puzzle

The goal of the 8 puzzle problem is to complete pieces on $3 \times 3$ cells where one of the cells is empty space.

In this problem, the space is represented by 0 and pieces are represented by integers from 1 to 8 as shown below.

1 3 0
4 2 5
7 8 6

You can move a piece toward the empty space at one step. Your goal is to make the pieces the following configuration in the shortest move (fewest steps).

1 2 3
4 5 6
7 8 0

Write a program which reads an initial state of the puzzle and prints the fewest steps to solve the puzzle.

Input

The $3 \times 3$ integers denoting the pieces or space are given.

Output

Print the fewest steps in a line.

Constraints

There is a solution.

Sample Input

1 3 0
4 2 5
7 8 6

Sample Output

4

Solution in C (judge verdict: Accepted)

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

// I/O
int get_uint() {
    int n = 0;
    int c = getchar_unlocked();
    if(c < 48 || 57 < c) return c;
    while(47 < c && c < 58) n = 10 * n + (c & 0xf), c = getchar_unlocked();
    return n;
}
void put_uint(int n) {
    if(!n) {
        putchar_unlocked('0');
        return;
    }
    char buf[11];
    int i = 0;
    while(n) buf[i++] = (char)(n % 10 + '0'), n /= 10;
    while(i--)putchar_unlocked(buf[i]);
}


// Node
typedef struct NodeKey {
    int board[9];
    int space;
    int cnt;
} NodeKey;
// lt: -1, gt: 1, eq: 0
int cmp_node(const NodeKey *l, const NodeKey *r) {
    for(int i = 0; i < 9; ++i) {
        if(l->board[i] == r->board[i]) continue;
        else if(l->board[i] < r->board[i]) return -1;
        else return 1;
    }
    return 0;
}


// Treap
typedef struct Node {
    NodeKey key;
    int priority;
    struct Node *left, *right;
} Node;
typedef struct BST {
    Node *root;
    size_t size;
} BST;
void bst_init(BST *BST) {
    BST->root = NULL;
    BST->size = 0;
}
Node *bst_rotate_right(Node *root) {
    Node *tmp = root->left;
    root->left = tmp->right;
    tmp->right = root;
    return tmp;
}
Node *bst_rotate_left(Node *root) {
    Node *tmp = root->right;
    root->right = tmp->left;
    tmp->left = root;
    return tmp;
}
Node *bst__insert(Node *root, const NodeKey key, const int priority) {
    if(root == NULL) {
        Node *new_node = malloc(sizeof(Node));
        new_node->key = key;
        new_node->priority = priority;
        new_node->left = new_node->right = NULL;
        return new_node;
    }
    if(cmp_node(&key, &root->key) == 0) return root;
    if(cmp_node(&key, &root->key) == -1) {
        root->left = bst__insert(root->left, key, priority);
        if(root->priority < root->left->priority) root = bst_rotate_right(root);
    } else {
        root->right = bst__insert(root->right, key, priority);
        if(root->priority < root->right->priority) root = bst_rotate_left(root);
    }
    return root;
}
void bst_insert(BST *BST, const NodeKey key, const int priority) {
    BST->root = bst__insert(BST->root, key, priority);
    BST->size++;
}
Node *bst_find(Node *root, const NodeKey key) {
    while(root != NULL && cmp_node(&key, &root->key)) {
        if(cmp_node(&key, &root->key) == -1) root = root->left;
        else root = root->right;
    }
    return root;
}


// Queue
#define QueueKey NodeKey
typedef struct QueueDat {
    QueueKey key;
    struct QueueDat *next;
} QueueDat;
typedef struct Queue {
    size_t len;
    QueueDat *head;
    QueueDat *tail;
} Queue;
#define queue_init(q) ((q) ? ((q)->len = 0, (q)->head = (q)->tail = NULL) : 0)
#define queue_len(q) ((q) ? (q)->len : 0)
void queue_push(Queue *q, QueueKey x) {
    QueueDat *new_dat = malloc(sizeof(QueueDat));
    *new_dat = (QueueDat){x, NULL};
    if(q->len) {
        q->tail->next = new_dat;
        q->tail = new_dat;
    } else {
        q->head = q->tail = new_dat;
    }
    q->len++;
}
QueueKey queue_pop(Queue *q) {
    QueueDat *old_head = q->head;
    q->head = old_head->next;
    QueueKey key = old_head->key;
    free(old_head);
    q->len--;
    return key;
}


// end condition
int is_solved(const int board[9]) {
    for(int i = 0; i < 8; ++i)
        if(board[i] != i + 1) return 0;
    return 1;
}


// solve
int bfs(NodeKey s) {
    const int N = 3;
    const int dx[4] = {-1, 0, 1, 0};
    const int dy[4] = {0, -1, 0, 1};
    srand((unsigned)time(NULL));
    BST BST;
    bst_init(&BST);
    bst_insert(&BST, s, rand());
    Queue Q;
    queue_init(&Q);
    queue_push(&Q, s);
    while(queue_len(&Q)) {
        NodeKey key = queue_pop(&Q);
        if(is_solved(key.board)) return key.cnt;
        int x = key.space % N;
        int y = key.space / N;
        for(int i = 0; i < 4; ++i) {
            int nx = x + dx[i];
            int ny = y + dy[i];
            if(nx < 0 || N <= nx || ny < 0 || N <= ny) continue;

            int next_space = nx + ny * N;
            NodeKey next_key = key;
            next_key.board[key.space] = next_key.board[next_space];
            next_key.board[next_space] = 0;
            next_key.space = next_space;
            if(bst_find(BST.root, next_key)) continue;

            next_key.cnt++;
            bst_insert(&BST, next_key, rand());
            queue_push(&Q, next_key);
        }
    }
}


int main(int argc, char **argv) {
    NodeKey initial;
    initial.cnt = 0;
    for(int i = 0; i < 9; ++i) {
        int x = get_uint();
        initial.board[i] = x;
        if(x == 0) initial.space = i;
    }
    put_uint(bfs(initial));
    putchar_unlocked('\n');
    return 0;
}