codevs 1225:八数码难题【双向广搜】

这里是传送门

这道题用普通BFS是可以做的,但是很明显没得过,效率太低了。效率更高的算法A*和双向广搜都可取,这写一下双向广搜的。

注意题目中的判重很重要,可以转化成九位数用hash来解决这个问题。

#include <set>
#include <string>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define oo 0x7f7f7f7f
#define str string
#define put(x) printf("%d\n", x)
#define cln(x) memset(x, 0, sizeof(x))
using namespace std;

str st;
str s[100005][2];
int h[2];
int t[2];
int b[100005][2];
set <str> hash[2];

void check(int x)
{
    if ( hash[1-x].count( s[t[x]][x] ) )
    {
        for (int i = 1; i <= t[1-x]; i++)
            if ( s[i][1-x] == s[t[x]][x] )
            {
                put(b[i][1-x]+b[t[x]][x]);
                break;
            }
        exit(0);
    }
}

str get( str s, int i )
{
    str x = s;
    int p = s.find(‘0‘);
    if ( i == 1 )
    {
        if ( p < 3 ) return "-1";
        swap( t[p], t[p-3] );
        return x;
    }
    if ( i == 2 )
    {
        if ( p == 0 || p == 3 || p == 6 ) return "-1";
        swap( t[p], t[p-1] );
        return x;
    }
    if ( i == 3 )
    {
        if ( p > 5 ) return "-1";
        swap( t[p], t[p+3] );
        return x;
    }
    if ( i == 4 )
    {
        if ( p == 2 || p == 5 || p == 8 ) return "-1";
        swap( t[p], t[p+1] );
        return x;
    }
}

void go(int x)
{
    h[x]++;
    str ss = s[h[x]][x];
    int c = b[h[x]][x] + 1;
    for ( int i = 1; i <= 4; i ++ )
    {
        str sss = get( ss, i );
        if ( sss == "-1" || hash[x].count(sss) ) continue;
        else
        {
            hash[x].insert(sss);
            t[x]++;
            b[t[x]][x] = c;
            s[t[x]][x] = sss;
            check(x);
        }
    }
}

void Double_BFS()
{
    h[0] = h[1] = 0;
    t[0] = t[1] = 1;
    s[1][0] = st;
    s[1][1] = "123804765";
    while( h[0] < t[0] && h[1] < t[1] )
    {
        if (t[0] < t[1])
            go(0);
        else
            go(1);
    }

}

int main()
{
    cin >> st;
    Double_BFS();
    return 0;
}
时间: 2024-08-07 17:02:19

codevs 1225:八数码难题【双向广搜】的相关文章

[LGOJ]P1379八数码难题[双向广搜].cpp

已知初始状态和目标状态时可用双向搜索 有种神仙代码实际上不对, 没有判重, 拓展了很多重复的状态节点 但还是能算出答案, 用小样例验证时还看不出来, 一交全TLE 所以千万要记得判重 详见代码, 自认为码风清奇 #include<cstdio> #include<map> #include<queue> #define re register using namespace std; int str,endd=123804765;//矩阵只有3*3大小, 用int存方便

双向广搜+hash+康托展开 codevs 1225 八数码难题

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

1225 八数码难题

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

wikioi 1225 八数码难题 IDA*

为什么就是跑不出0ms 八数码0.0,我又来水博客了. IDA*算法,A*为曼哈顿距离,判重用康拓展开. #include<cstring> #include<cstdio> #include<iostream> #include<cmath> #include<algorithm> using namespace std; int a[4][4]; int dx[]={0,0,-1,1}; int dy[]={-1,1,0,0}; char s

codevs1225八数码难题(搜索&#183;)

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

双向广搜 codevs 3060 抓住那头奶牛

codevs 3060 抓住那头奶牛 USACO 时间限制: 1 s 空间限制: 16000 KB 题目等级 : 黄金 Gold 题目描述 Description 农夫约翰被告知一头逃跑奶牛的位置,想要立即抓住它,他开始在数轴的N 点(0≤N≤100000),奶牛在同一个数轴的K 点(0≤K≤100000).约翰有两种移动方式:1 分钟内从x 点移动到x+1 或x-1:1 分钟内从x 点移动到2x.假设奶牛不会移动,约翰抓住它需要多少时间? 输入描述 Input Description 一行两个

双向广搜 开始!!!

先简单的了解一下,双向广搜很好理解,就是从两端一起搜,如果遇到之前已经搜到过的状态,就相当于已经有解了,这样就会节省一半的内存和时间,并且代码复杂度并不高.只需要在正常的基础上多开一个域,保存这个点是从起始状态还是终止状态拓展的.当然双向广搜中状态的判断需要一些技巧,现在还没有总结出什么. 八数码问题: 很经典的一种双向广搜,因为只有九个数,所以用康托展开作为hash值.拓展时,如果这个hash值已经访问过,就判断,如果是两条路过来的就输出,否则就继续做:对于没有访问过的hash值就可以添加到队

双向广搜

双向广搜 (2011-08-31 16:45:24)   Eight    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1043 讲到双向广搜,那就不能不讲经典的八数码问题,有人说不做此题人生不完整 . 所谓双向广搜,就是初始结点向目标结点和目标结点向初始结点同时扩展,直至在两个扩展方向上出现同一个结点,搜索结束.它适用的问题是,扩展结点较多,而目标结点又处在深沉,如果采用单纯的广搜解题,搜索量巨大,搜索速度慢是可想而知的,同时往往也会出现内存空

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

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