首页 > 代码库 > 八数码问题

八数码问题

//八数码问题
typedef int State[9];
const int maxstate = 1000000;
State st[maxstate], goal//所有转换的状态和终点状态
int dist[maxstate];
const int dx[] = {-1, 1, 0, 0};
const int dy[] = {0, 0, -1, 1};

int bfs() {
    init_lookup_table();
    int front = 1, rear = 2;
    while(front < rear) {
        State &s = st[front];//弹出队头状态
        if (memcmp(goal, s, sizeof(s)) == 0) return front;//找到目标状态
        int z;
        for (z = 0; z < 9; z ++) if(!s[z]) break;//找到0的位置;
        int x = z / 3, y = z % 3;
        for (int d = 0; d < 4; d ++) {
            int newx = x + dx[d];
            int newy = y + dy[d];
            int newz = newx * 3 + newy;
            if (newx >=0 && newx < 3 && newy >=0 && newy <3) {
                steat &t = st[rear]; //拓展新节点
                memcpy(&t, &s, sizeof[t]);
                t[newz] = s[z];
                t[z] = s[newz];
                dist[rear] = dist[front] + 1;
                if(try_to_instert(rear)) rear++;//如果可以插入节点,则将新节点拓展
            }
        }
        front ++;
    }
    return 0;
}

//用hashtable存储已遍历节点
const int hashsize = 1000003;
int head[hashsize], next[maxstate];
void init_lookup_table() {
    memset(head, 0 ,sizeof(head));
}
int hash(State &s) {
    int v = 0;
    for (int i = 0; i < 9; i ++) {
        v =v * 10 + s[i];
    }
    return v % hashsize;
}
int try_to_instert(int s) {
    int h = hash(st[s]);
    int u = head[h];
    while(u) {
        if(memcmp(st[u], st[s], sizeof(st[u])) == 0) 
            return false;
        u = next[u];
    }
    next[s] = head[h];
    head[h] = s;
    return 1;
}

//将节点转换为9位十进制整数,并用set统计。
set<int> vis;
void init_lookup_table() {
    vis.clear();
}
int try_to_instert(int s) {
    int v = 0;
    for (int i = 0; i < 9; i++) {
        v = v * 10 +st[s][i];
    }
    if(vis.count(v)) return 0;
    vis.insert(v);
    return 1;
}

 

八数码问题