八数码问题

//八数码问题
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;
}
时间: 2024-10-10 02:32:33

八数码问题的相关文章

1225 八数码难题

1225 八数码难题 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 钻石 Diamond 题解 查看运行结果 题目描述 Description Yours和zero在研究A*启发式算法.拿到一道经典的A*问题,但是他们不会做,请你帮他们.问题描述 在3×3的棋盘上,摆有八个棋子,每个棋子上标有1至8的某一数字.棋盘中留有一个空格,空格用0来表示.空格周围的棋子可以移到空格中.要求解的问题是:给出一种初始布局(初始状态)和目标布局(为了使题目简单,设目标状态为123804765

HDU 1043 Eight八数码解题思路(bfs+hash 打表 IDA* 等)

题目链接 https://vjudge.net/problem/HDU-1043 经典的八数码问题,学过算法的老哥都会拿它练搜索 题意: 给出每行一组的数据,每组数据代表3*3的八数码表,要求程序复原为初始状态 思路: 参加网站比赛时拿到此题目,因为之前写过八数码问题,心中暗喜,于是写出一套暴力bfs+hash,结果TLE呵呵 思路一:bfs+hash(TLE) 1 #include <cstdio> 2 #include <cstring> 3 #include <queu

洛谷【P1379】八数码难题

P1379 八数码难题 题目描述 在3×3的棋盘上,摆有八个棋子,每个棋子上标有1至8的某一数字.棋盘中留有一个空格,空格用0来表示.空格周围的棋子可以移到空格中.要求解的问题是:给出一种初始布局(初始状态)和目标布局(为了使题目简单,设目标状态为123804765),找到一种最少步骤的移动方法,实现从初始布局到目标布局的转变. 输入输出格式 输入格式: 输入初试状态,一行九个数字,空格用0表示 输出格式: 只有一行,该行只有一个数字,表示从初始状态到目标状态需要的最少移动次数(测试数据中无特殊

八数码三种用时差距极大的写法

进化史,一种比一种长,一种比一种快.不过第三种似乎还不是最终形态. 第一种,傻逼级迭代加深. 去年十一月写的,那时候刚刚学迭代加深,敲了一个钟头才敲完,codevs上直接过,就没太管,觉得这是个水题.实际上呢,看后文. 1 #include<algorithm> 2 #include<iostream> 3 #include<cstring> 4 #include<cstdio> 5 using namespace std; 6 int sx,sy,lim,

八数码的八境界 [转载]

八数码的八境界   研究经典问题,空说不好,我们拿出一个实际的题目来演绎.八数码问题在北大在线测评系统中有一个对应的题,题目描述如下: Eight Time Limit: 1000MS    Memory Limit: 65536K  Special Judge Description The 15-puzzle has been aroundfor over 100 years; even if you don't know it by that name, you've seen it. I

【转】八数码问题及A*算法

一.八数码问题八数码问题也称为九宫问题.在3×3的棋盘,摆有八个棋子,每个棋子上标有1至8的某一数字,不同棋子上标的数字不相同.棋盘上还有一个空格,与空格相邻的棋子可以移到空格中.要求解决的问题是:给出一个初始状态和一个目标状态,找出一种从初始转变成目标状态的移动棋子步数最少的移动步骤.所谓问题的一个状态就是棋子在棋盘上的一种摆法.棋子移动后,状态就会发生改变.解八数码问题实际上就是找出从初始状态到达目标状态所经过的一系列中间过渡状态.八数码问题一般使用搜索法来解.搜索法有广度优先搜索法.深度优

HDU 3567 Eight II(八数码 II)

p.MsoNormal { margin: 0pt; margin-bottom: .0001pt; text-align: justify; font-family: Calibri; font-size: 10.5000pt } h1 { margin-top: 5.0000pt; margin-bottom: 5.0000pt; text-align: center; font-family: 宋体; color: rgb(26,92,200); font-weight: bold; fo

cdoj 1380 Xiper的奇妙历险(2) [八数码问题 bfs + 预处理]

快要NOIP 2016 了,现在已经停课集训了.计划用10天来复习以前学习过的所有内容.首先就是搜索. 八数码是一道很经典的搜索题,普通的bfs就可求出.为了优化效率,我曾经用过康托展开来优化空间,甚至还用过A*来优化时间.不过这道题懒得写了,就一个普普通通的bfs,再加上一个stl 的map就水过了. 首先题目要求有多达10000组数据,依次搜索肯定是不行的,我试过用A*来写,第2组数据就会T掉,所以我们考虑用一个预处理.从末尾状态搜索所有可行的状态,并用一个map来存储答案.然后就很好写了.

BFS(八数码) POJ 1077 || HDOJ 1043 Eight

题目传送门1 2 题意:从无序到有序移动的方案,即最后成1 2 3 4 5 6 7 8 0 分析:八数码经典问题.POJ是一次,HDOJ是多次.因为康托展开还不会,也写不了什么,HDOJ需要从最后的状态逆向搜索,这样才不会超时.判重康托展开,哈希也可. POJ //#include <bits/stdc++.h> #include<iostream> #include<algorithm> #include<string> #include<stack

洛谷OJ P1379 八数码难题 解题报告

洛谷OJ P1379 八数码难题 解题报告 by MedalPluS 题目描述   在3×3的棋盘上,摆有八个棋子,每个棋子上标有1至8的某一数字.棋盘中留有一个空格,空格用0来表示.空格周围的棋子可以移到空格中.要求解的问题是:给出一种初始布局(初始状态)和目标布局(为了使题目简单,设目标状态为123804765),找到一种最少步骤的移动方法,实现从初始布局到目标布局的转变.   输入格式   输入初试状态,一行九个数字,空格用0表示   输出格式 只有一行,该行只有一个数字,表示从初始状态到