Eight II (HDU - 3567,BFS 打表 + 思维)

HDU(3567):八数码问题(升级版)——双BFS 题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3567   有了HDU 1043的基础,此题就变得比较容易了,如果用A*算法,感觉路径不太好打印,所以就放弃了,看到有一种好像和1043一样的打表法,但是没怎么能理解,也就放弃了,虽然要打印最小字典序,单向BFS显然会TLE,所以我只能用双向BFS了。   好在,此题的输入保证有解,否则还得用一 阅读详情

一.题目链接:

HDU-3567

二.题目大意:

Eight 的升级版,游戏规则相同.

每次给出两个字符串 A, B,问 从 A 到 B 的最少步数 并 打印最小字典序的路径.

三.分析:

看了大神的分析才懂。。。

在这里阐述一下.

只考虑 X 的位置,由于 1 ~ 8 数字无特殊性

所以可将所给的 A 重新编号.

例如 A1:8 7 X 6 5 4 3  2 1

编号为 A2:1 2 X 3 4 5 6 7 8 

并使用相同的编号规则 给字符串 B 重新编号

这样 A2 -> B2 就等价与 A1-> B1.

又因为 X 的位置只有 9 种情况,所以可以先用 BFS 打表

之后重新编号 + 查询即可.

四.代码实现:

#include <set>
#include <map>
#include <ctime>
#include <queue>
#include <cmath>
#include <stack>
#include <vector>
#include <cstdio>
#include <sstream>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#define eps 1e-6
#define pi acos(-1.0)
#define ll long long int
using namespace std;

const int M = (int)5e5;

struct node
{
    int D[9];
    int x;
    int y;
};

bool vis[M + 5];
int fa[9][M + 5];
int inflection[9];
char dir[9][M + 5];

int Move[4][2] = {{1, 0}, {0, -1}, {0, 1}, {-1, 0}};

int cantor(struct node p)
{
    int sum = 0;
    int fac = 40320;
    for(int i = 0; i < 9; ++i)
    {
        int cnt = 0;
        for(int j = i + 1; j < 9; ++j)
        {
            if(p.D[j] < p.D[i])
                cnt++;
        }
        sum += fac * cnt;
        if(i == 8)
            return sum;
        fac /= 8 - i;
    }
}

void bfs(struct node p, int op)
{
    memset(vis, 0, sizeof(vis));
    struct node t;
    queue <node> q;
    int can1 = cantor(p);
    int can2;
    vis[can1] = 1;
    q.push(p);
    while(!q.empty())
    {
        p = q.front();
        q.pop();
        can1 = cantor(p);
        for(int i = 0; i < 4; ++i)
        {
            t = p;
            t.x += Move[i][0];
            t.y += Move[i][1];
            if(t.x < 0 || t.x >= 3 || t.y < 0 || t.y >= 3)
                continue;
            int pos = t.x * 3 + t.y;
            if(i == 0)
            {
                swap(t.D[pos], t.D[pos - 3]);
                can2 = cantor(t);
                if(!vis[can2])
                {
                    vis[can2] = 1;
                    dir[op][can2] = 'd';
                    fa[op][can2] = can1;
                    q.push(t);
                }
            }
            else if(i == 1)
            {
                swap(t.D[pos], t.D[pos + 1]);
                can2 = cantor(t);
                if(!vis[can2])
                {
                    vis[can2] = 1;
                    dir[op][can2] = 'l';
                    fa[op][can2] = can1;
                    q.push(t);
                }
            }
            else if(i == 2)
            {
                swap(t.D[pos], t.D[pos - 1]);
                can2 = cantor(t);
                if(!vis[can2])
                {
                    vis[can2] = 1;
                    dir[op][can2] = 'r';
                    fa[op][can2] = can1;
                    q.push(t);
                }
            }
            else if(i == 3)
            {
                swap(t.D[pos], t.D[pos + 3]);
                can2 = cantor(t);
                if(!vis[can2])
                {
                    vis[can2] = 1;
                    dir[op][can2] = 'u';
                    fa[op][can2] = can1;
                    q.push(t);
                }
            }
        }
    }
}

void init()
{
    struct node p, t;
    for(int i = 0; i < 9; ++i)
        p.D[i] = i + 1;
    for(int i = 0; i < 9; ++i)
    {
        t = p;
        t.D[i] = 0;
        t.x = i / 3;
        t.y = i % 3;
        bfs(t, i);
    }
}

 int read(struct node &p)
{
    int op;
    char ch;
    int pos = 0;
    while((ch = getchar()) != '\n')
    {
        if(ch == 'X')
        {
            op = pos;
            p.D[pos++] = 0;
        }
        else if(ch >= '1' && ch <= '8')
            p.D[pos++] = ch - '0';
    }
    return op;
}

int main()
{
    init();
    int T;
    scanf("%d", &T);
    getchar();
    for(int ca = 1; ca <= T; ++ca)
    {
        struct node p1, p2;
        int op = read(p1);
        read(p2);
        for(int i = 0; i < 9; ++i)
        {
            if(!p1.D[i])
                continue;
            inflection[p1.D[i]] = i + 1;
            p1.D[i] = i + 1;
        }
        for(int i = 0; i < 9; ++i)
        {
            if(!p2.D[i])
                continue;
            p2.D[i] = inflection[p2.D[i]];
        }
        int can1 = cantor(p1);
        int can2 = cantor(p2);
        stack <char> st;
        while(can1 != can2)
        {
            st.push(dir[op][can2]);
            can2 = fa[op][can2];
        }
        printf("Case %d: %d\n", ca, st.size());
        while(!st.empty())
        {
            printf("%c", st.top());
            st.pop();
        }
        printf("\n");
    }
    return 0;
}

 

HDU 3567 Eight II (八数码) 双向BFS 和 BFS打表 HDU 3567 Eight II (八数码) 双向BFS 和 BFS打表 八个数码八重境界,说的很有道理。你们要是有精力可以把所有的都试一下 我干不动了 到这里就退了哈哈哈。 如果没有做过1043的建议先去做一下1043. HDU1043 附上1043的题解1043题解 双向bfs: 话不多说了来看一下题意。和1043很像 如果没做过1043可以做一下。区别就是 1043更简单,1043说的... 阅读详情

相关推荐

Ubuntu 24.04.3 LTS 安装 OpenClaw 图文版

OpenClow安装指南

qq_17204557的博客 2551

hdu 3567 Eight II 八数码 双向BFS

代码:

冷月之殇 3390

RP Fiber Power 版本

RP Fiber Power的版本历史 该软件一直受到多年来广泛的发展计划,这大大扩展了其功能,以及用户界面的质量。 V1 这是第1个版本。 它仅限于光纤激光器和放大器的连续波计算,并且只能通过脚本进行控制。 V2 版本2引入了交互式表单。 至少对于更简单的模拟,现在可以简单地通过填写表单来工作,而V1必须通过脚本来控制。 例如,屏幕截图显示了输入某些信号参数的表单: 当您基于这些表单执行计算时,程序将根据您的表单输入自动编写脚本文件,然后执行该脚本。如果您需要编写脚本以获得更大的灵活性,可以稍后查看该脚

Asdmath的博客 2432

【HDU No. 3567】八数码 II Eight II

【HDU No. 3567】八数码 II Eight II

代码改变世界 737

计算机组成原理实验二 运算器组成实验

事实上,ALU的设计是在全加器的基础上,对全加器功能的扩展来实现符合要求的多种算术/逻辑运算的功能。为了实现多种功能的运算,An、Bn数据是不能直接与全加器相连接的,它们受到功能变量F3—F1的制约,因此,可由An、Bn数据和功能变量F3-F1组合成新的函数Xn 、Yn,然后,再将Xn 、Yn和下一位进位Cn-1通过全加器进行全加运算以实现所需的运算功能。AC寄存器可用来存储ALU的输入以实现两个操作数的运算操作,也可以用来存储来自ALU的结果,以将这些结果反馈给ALU以进行更多的处理。

qq_63574533的博客 1450

减小伺服电机共振的方法(以松下伺服为例)

嘿 ! 我是【小黄】 , 我们又见面啦 !!! 毕竟技术只有大家交流才会进步嘛 ! 这博客是对自己学习的一点点记录和总结 ,如果您对自动控制感兴趣的话 ,可以关注一下我的动态 , 我们一起学习呀 ! 我们都还年轻 ,我们还有无限可能 。 YES ! 减小伺服电机共振的方法(以松下伺服为例)1. 准备工作:1.1.1 如何推定共振点:1.1.2 测定实操:1.1.3 总结:2. 下期预告: 在我们调试完伺服参数以后机器人运动到某个特定位置会产生振动或异响,我们要做的就是消除这个异响保..

在下小黄的博客 1万+

hdu 3567(八码数 + 双向bfs)

题目连接:https://vjudge.net/contest/353606#problem/B 参考文章:https://blog.youkuaiyun.com/laaahu/article/details/96648344 思路: 广搜,记录路径,因为最多的交换次数不会太多,所以可以用int类型的4进制数记录路径;因为要求字典序最小,所以走得方向是dlru,当每次找到合法的路径时判断是否是字典...

积少成多,水滴石穿 658

定时移动鼠标点击鼠标,防止电脑息屏的vba脚本

定时移动鼠标,使系统始终处于激活状态,防止系统息屏。

panfei263031的博客 5931

【kuangbin带你飞--进阶搜索专题】Eight II

Eight-puzzle, which is also called "Nine grids", comes from an old game. In this game, you are given a 3 by 3 board and 8 tiles. The tiles are numbered from 1 to 8 and each covers a grid. As you see,...

qq_42711300的博客 284

Ubuntu搭建Pytorch环境(Anaconda、Cuda、cuDNN、Pytorch、Python、Pycharm、Jupyter)

Ubuntu搭建Pytorch环境(Anconda、Cuda、Pytorch、Python、Pycharm、Jupyter)

funfan的博客 1万+

微搭低代码实现用户登录及注册功能

在小程序开发中,我们可以拿到微信用户的openid,openid可以作为用户的唯一标识,在查询数据的时候可以进行数据过滤实现查询自己提交的数据。那微搭中是否也有openid这个概念,可以获取用户自己提交的数据呢? 答案是肯定的,那要怎么去做呢?思路是先创建一个数据源方法,在数据源中返回openid,然后低代码中可以调用数据源的方法并且赋值给全局变量,这样在后续的业务中从全局变量就可以获取openid了,方便做数据权限的控制。 为了实现这个目的,我们从创建数据源开始。 创建数据源 我们先创建一个用户管理的数据

低代码布道师的博客 3000

HDU 3567 Eight II(BFS打表)

题目大意   还是八数码问题,输入起始结束状态,输出最小字典序的操作顺序 思路   还是用BFS打表,为了使操作最短,处理出X在不同位置不断操作能达到的各种状态,至于为什么根据X的不同处理,除了X外,其他数字可以随意替换,如: 1 2 3      3 4 5 4 5 6   =>  7 8 X 7 8 X      6 2 1 可以替换成 a b c      c d e d e f   ...

IuSpet的博客 323

Python爬虫实战:使用最新技术抓取百度贴吧帖子内容

本文详细介绍了使用Python最新技术抓取百度贴吧帖子的完整流程。通过库,我们实现了高效的异步爬虫,具备JavaScript渲染、智能反爬应对、数据持久化等高级功能。这个爬虫框架具有良好的扩展性,可以根据具体需求进行功能增强。

2201_76125261的博客 779

HDU 3567 Eight II (BFS+映射+康托展开)

题面 Eight-puzzle, which is also called "Nine grids", comes from an old game. In this game, you are given a 3 by 3 board and 8 tiles. The tiles are numbered from 1 to 8 and each covers a grid. As you s...

Yi_Qing_Z的博客 1028

霍尼韦尔SoftMaster使用说明

霍尼韦尔SoftMaster使用说明

廖雪峰Python教程[完整版]

廖雪峰的python教程整理的,已经排好版了,而且还是完整的,适合小白

HDU 3567 Eight II 预处理+bfs+hash

传送门:HDU3567 题意:经典八数码问题,将八数码从状态A转化到状态B,问最短且字典序最小的解法。 思路:先说说我自己吧,我是刚做完了POJ1077就来做这个题,当时感觉这不是一样的么,改个bfs结束条件不就完事了,然后就一发wa。。看题解才发现A*算法不能保证输出结果是字典序最小的,仔细想想,好像确实是,因为A*中F=G+H的等式是为了更快的求得解,我们每次从优先队列中取出来的状态是F值

WA是一笔财富 1287

精雕软件(JDpaint) 5.5 绿色版

精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版

【双向BFS搜索】hdu3567Eight II

http://acm.hdu.edu.cn/showproblem.php?pid=3567 题目大意:8数码问题。给定起始状态和目标状态,求最少移动次数和字典序最小的方案。(r:向右,l:向左,u:向上,d:向下)用单向BFS–>无限TLE 可以用双向BFS和A∗A^*搜索,但注意由于要求字典序最小,无论是双向BFS,还是A∗A^*搜索都无法保证最先出现的解字典序最小。无奈只得将最小移动次数全

蒟蒻的奋斗史 1054

ET2012新版免狗免安装绿色软件

ET2012新版免狗免安祖昂绿色软件。,新界面,新视觉,

HDU3567(Eight II)

Eight II 题目传送门 Problem Description Eight-puzzle, which is also called “Nine grids”, comes from an old game. In this game, you are given a 3 by 3 board and 8 tiles. The tiles are numbered from 1 to 8 and each covers a grid. As you see, there is a blank grid

weixin_43808717的博客 285

Eight II HDU - 3567写题报告

题目链接 原题链接 难度分析 这题啊,这题也不是很难,总的来说就是:思维+bfs逆向路径打印+打表+康托展开 我花了两天,tle四次,mle4次然后就写出来的。写完以后神清气爽,就想说一句我(w)带(d)你(n)们(m)打(d)icpc。 题解 由于每次都是改变x的位置,而x只可能出现在方块的9个位置中,所以可以根据x的位置进行分类,,然后别打表,然后再进行映射处理,得到答案。 具体来说,就是分别以 12345678x 1234567x8 123456x78 12345x678 1234x5678 123

SCUEC__zhazhahui的博客 273

HDU - 3567 Eight II 【bfs打表+映射+康托展开】

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3567 这道题比较容易想到的就是双向bfs,在时间上是比较理想的,但是在内存上就比较紧张。 网上看到有人用映射的技巧做这题。 假设我知道起点是 12345678x这个状态到其他状态的所有路径。对于所有起点是 ********x这个状态到其他状态的所有路径我也能够知道。 假设我知道12x34567...

Y390d的博客 358

HDU 3567 Eight II 八数码(2)

转载请注明出处,谢谢 http://blog.youkuaiyun.com/ACM_cxlove?viewmode=contents           by---cxlove 八数码的升级版,给定起点,终点,双向BFS可破。有了魔板那题的基础。 同样对这题进行预处理,不过需要注意的是,这题有不同的情况,也就是空位X造成的,所以枚举X的位置,9种置换,进行BFS。 对于每一种起点,保存所有的能到达状

窝不是爱酱,喵~~~~ 2450

HDU-3567 Eight II

八数码问题,给出初始状态和结束状态,要输出最短移动路径中字典序最小的那个,输入保证有解因为数据量比较多,不能单纯的BFS,双向BFS也不能保证字典序,这里利用了映射的思想以及打表先以X12345678,1X2345678.....,1234567X8,12345678X为开始进行BFS,把路径分开保存好然后将起始状态映射为以上其中的一个(X的位置一样的那个),相应的把结束状态转变过去,再寻找路径回...

wl16wzl的博客 319

B - Eight II HDU - 3567(bfs+预处理)

B - Eight II HDU - 3567 思路 这一题由于是多组输入,如果我们对每一组输入都进行一遍 bfs 这样肯定会T, 那么这一题的,奇妙思路就是预处理所有可能产生的终点状态,进行bfs逆向bfs 我们假设所以的逆向状态为: “X12345678”, “1X2345678”, “12X345678”, “123X45678”, “1234X5678”, “12345X678”, “123456X78”, “1234567X8”, “12345678X”, 对于题目的中给我两个 起始、终

做一只熊猫不好吗? 315

HDU 3567 Eight II

//HDU 3567 Eight II //Eight的进阶版 //1.划归思想,将所有问题归为九种以X的位置进行讨论 //2.路径的记录与每个节点的特殊标记关联,该题便通过vis[][]起到记录路径的作用 //3.有顺序的广搜 //4.康托展开hash构造 #include<bits/stdc++.h> using namespace std; const int maxn = 4e5; //大于9! const int fac[10]={1,1,2,6,24,120,720,5040,

qq_46194023的博客 198

HDU 3567 Eight II(八数码 II)

HDU 3567 Eight II(八数码 II) TimeLimit:4000/2000MS(Java/Others)MemoryLimit:130000/65536K(Java/Others) ProblemDescription - 题目描述   Eight-puzzle, which is also called "Nine ...

352

HDU3567:Eight II(康拓展开+预处理)

Problem Description Eight-puzzle, which is also called "Nine grids", comes from an old game.  In this game, you are given a 3 by 3 board and 8 tiles. The tiles are numbered from 1 to 8 and each

ACM!荣耀之路! 4944
上一篇: Eight (HDU - 1043,反向 BFS + 康拓展开)
下一篇: Escape (HDU - 3533,BFS + 模拟)
The___Flash
博客等级 码龄8年 79粉丝 223原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值