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

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

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3567

这道题比较容易想到的就是双向bfs,在时间上是比较理想的,但是在内存上就比较紧张。

网上看到有人用映射的技巧做这题。

假设我知道起点是 12345678x这个状态到其他状态的所有路径。对于所有起点是 ********x这个状态到其他状态的所有路径我也能够知道。

假设我知道12x345678 这个状态到其他状态的路径。

而样例1要求 12x453786 到 123456789x的路径,我们存在这么一个映射(起点状态的映射)

1 --> 1

2 --> 2

4 --> 3

5 --> 4

3 --> 5

7 --> 6

8 --> 7

6 --> 8

按照上面的映射,我们要求的终点状态不再是 12345678x,而是12534867x

这时候我们要求的问题就变成起点为 12x345678 到终点 12534867x 的最短路径。

根据x的位置,我们只需要预先打表9种情况的路径,通过映射关系直接求出答案。

这种方法在时间上是比较理想的,其次存储答案的时候要注意内存上的限制,如果9种状态的路径统一保证下来的话,内存上是很紧张的。在存储路径的时候,我们不需要存储一整段路径,每一个状态只存一步的路径,并且记录好上一步状态的康托展开编号,当我们需要得到路径的时候,通过不断访问上一步康托展开编号去获取路径。这样每一个状态只需要存一个char和int。

因为这道题在时间上是比较紧张的,要注意不要有一些浪费时间而不必要的操作,比如输出路径的时候一个一个的输出(G++会超时,要存到字符串里面以字符串的形式输出)。

#include <iostream>
#include <queue>
#include <cstring>
#include <string>
#include <map>
#include <cstdio>
#include <cmath>
#include <algorithm>

using namespace std;

const int INF = 0x3f3f3f3f;
const int Maxn = 4e5+10;

struct Node {
    int pre, step;
    char c;
} node[11][Maxn];

struct nNode {
    char str[10];
    int pos, st, step;
};

char ch[5] = "dlru", s[10][10] = {"012345678", "102345678", "120345678", "123045678", "123405678",
"123450678", "123456078", "123456708", "123456780"}, ans[50];
int dir[4][2] = { {1, 0}, {0, -1}, {0, 1}, {-1, 0} }, n[15], Hash[10];
bool vis[Maxn];

int cantor(char *ss) {
    int ret = 0;
    for(int i = 0; i < 9; ++i) {
        int cnt = 0;
        for(int j = i+1; j < 9; ++j) {
            if(ss[j] < ss[i]) cnt++;
        }
        ret += n[8-i]*cnt;
    }
    return ret;
}

void bfs(int x) {
    memset(vis, false, sizeof(vis));
    queue<nNode> qu;
    int state = cantor(s[x]);
    vis[state] = true;
    nNode tmp;
    tmp.pos = x; tmp.st = state; tmp.step = 0;
    memcpy(tmp.str, s[x], sizeof(tmp.str));
    qu.push(tmp);

    while (!qu.empty()) {
        tmp = qu.front(); qu.pop();

        for(int i = 0; i < 4; ++i) {
            nNode now = tmp;
            int pi, pj;

            pi = now.pos/3+dir[i][0]; pj = now.pos%3+dir[i][1];
            if(pi < 0 || pi > 2 || pj < 0 || pj > 2) continue;
            swap(now.str[pi*3+pj], now.str[now.pos]);
            now.pos = pi*3+pj;
            state = cantor(now.str);
            if(vis[state]) continue;
            vis[state] = true;
            node[x][state].c = ch[i]; node[x][state].pre = tmp.st;
            node[x][state].step = tmp.step+1;
            now.st = state; now.step = tmp.step+1;
            qu.push(now);
        }
    }
}

void init() {
    for(int i = 0; i < 10; ++i)
        for(int j = 0; j < Maxn; ++j) node[i][j].pre = -1;

    n[0] = 1;
    for(int i = 1; i <= 10; ++i) n[i] = n[i-1]*i;
    for(int i = 0; i < 9; ++i) bfs(i);
}

int main(void)
{
    int T;
    init();
    scanf("%d", &T);
    for(int cas = 1; cas <= T; ++cas) {
        char str1[10], str2[10];
        scanf("%s%s", str1, str2);
        int pos;
        for(int i = 0; i < 9; ++i) {
            if(str1[i] == 'X') {
                str1[i] == '0'; pos = i;
            }
            if(str2[i] == 'X') str2[i] == '0';
        }
        for(int i = 0; i < 9; ++i) Hash[str1[i]-'0'] = s[pos][i]-'0';
        for(int i = 0; i < 9; ++i) str2[i] = Hash[str2[i]-'0']+'0';
        str2[9] = '\0';
        int state = cantor(str2);
        int cnt = node[pos][state].step;
        int p = cnt;

        printf("Case %d: %d\n", cas, cnt);
        while (node[pos][state].pre != -1) {
            ans[--cnt] = node[pos][state].c;
            state = node[pos][state].pre;
        }
        ans[p] = '\0';
        printf("%s\n", ans);
    }
	return 0;
}

 

[kuangbin]专题二 搜索进阶 Eight II HDU - 3567【反向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 see... 阅读详情

相关推荐

数字设计实验:RISC-V指令单周期CPU

本文旨在介绍RISC-V指令单周期CPU的设计思路和仿真实现(含代码)

2401_83740084的博客 2713

hdu 3567(八码数 + 双向bfs)

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

积少成多,水滴石穿 658

ANSYS APDL齿轮建模实战:从渐开线方程到完整3D模型的保姆级教程

本文详细介绍了使用ANSYS APDL进行齿轮建模的全过程,从渐开线方程的数学基础到完整3D模型的创建。通过参数化命令流实现高精度齿轮建模,特别适合机械设计和仿真分析需求。教程包含关键参数计算、APDL环境配置、单齿齿廓建模以及全齿轮阵列复制等实用技巧,帮助工程师快速掌握ANSYS APDL在齿轮建模中的应用。

lg888的博客 447

hdu 3567(八数码问题 双向BFS)

题意:八数码问题,给了状态A,B,求A-&gt;B的最少变化次数,有多组最少则输出字典序最小的。可以先做这道http://acm.hdu.edu.cn/showproblem.php?pid=1043。这道简单些。 思路:双向BFS,同时从起点,终点进行搜索。这里以一个整数来表示路径。 从起点搜索,路径表示为 从终点搜索,路径表示为 这里i的取值为0~3,即空白点的不同移动所代表的数字,s...

m0_37514283的博客 1594

手把手教你用ADS仿真FMMT417雪崩三极管,搞定射频脉冲源设计

本文详细介绍了如何使用ADS仿真工具设计基于FMMT417雪崩三极管的射频脉冲源。从器件选型、SPICE模型导入到电路设计与优化,提供了一套完整的实操方案,特别适合射频脉冲设计的初学者。通过级联设计和实测验证,帮助工程师快速掌握雪崩电路的应用技巧,提升射频脉冲源的设计效率。

weixin_30905981的博客 491

autoDL算力云装Xinference[坑与步骤]

在页面直接点击下载会出现下着下载进度条消失,试了几次才出现这个报错,现在我们就继续安装缺少的包吧。这一步成功绕开了系统盘空间限制。先租用一个合适的服务器,建议不要选最新版本,跟我选的一样即可,不然后面会出现。最近在 AutoDL 上尝试部署。🚫 不要直接使用以下命令。点击下面链接即可打开。

ngadminq的博客 2383

HDU-3567 Eight II (DBFS+康托展开)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3567 参考代码:https://www.xuebuyuan.com/3266380.html 本题最难的点在于如何按字典序来输出 根据上面参考的博客发现最重要的点有: 1.当反向bfs找到时直接跳过这一步,因为不能把正向bfs的结果覆盖掉; 2.反向找的时候出现了重复要判断该次重复是否能构成更小的字...

TK_wang_的博客 1096

UWB灵犀遥控器方案介绍

UWB灵犀指向遥控器的技术原理和方案介绍

xiongdauwb的博客 3900

HDU - 3567 Eight II(IDA*)

HDU - 3567 题意: 给两个九宫格,你只能让X和与X相邻的格子进行交换,请从状态a得到状态b,要求移动次数最少且答案的字典序最小 思路: 稍有难度的一道搜索,我们需要用到IDA* 算法(还有其他很多种方法,有兴趣的可以自行尝试,这里使用的是IDA* 进行解答) 利用A* 算法来得到最小的移动次数的期望值,然后利用ID算法来进行迭代加深,如果了解 IDA* 算法的话,这道题就是一道板子题 (注意:A* 算法得到的最小移动次数是小于等于实际次数的,不理解的话可以查阅一下关于A* 算法的资料) 代码附:

qq_43586463的博客 272

OpenCV-Python实战(26)——复杂场景下的实时物体检测与跟踪

本节介绍了一种鲁棒的特征跟踪方法,该方法速度足够快,能够实时应用于网络摄像头的视频流。首先,算法展示了如何在一幅图像中提取和检测重要特征——无论是我们感兴趣的模板图像(训练图像),还是预期包含该物体的更复杂场景(查询图像),这些特征都具有视角和尺寸不变性。然后对关键点进行聚类,找到两幅图像中特征点之间的匹配。在此基础上,可以计算出一个将一组特征点映射到另一组的透视变换矩阵。利用这些信息,我们可以在查询图像中勾勒出训练图像的轮廓,并对查询图像进行透视变换,使感兴趣的物体以直立状态显示在屏幕中央。

盼小辉丶的博客 1929

基于STM32的嵌入式平台实现EtherCAT主站

本文将介绍如何在基于STM32的嵌入式平台上构建EtherCAT主站,并提供相应的源代码。使用SOEM库提供的API函数,我们可以实现与EtherCAT从站设备的实时通信和数据交换。在STM32的代码中,使用SOEM库提供的API函数初始化EtherCAT主站。在SOEM库中,我们可以找到EtherCAT主站的实现代码和相关的API函数。使用SOEM库提供的API函数实现EtherCAT主站的功能,包括发送和接收EtherCAT数据帧、处理从站设备的状态等。确保连接正常并且设备能够相互通信。

CodeSageX的博客 2834

Eight II HDU - 3567 (bfs打表+hash映射+康托展开)

Eight II HDU - 3567 Eight-puzzle, which is also called "Nine grids", comes from an old game. In this game, you are given a 3 by 3 boar...

codeswarrior的博客 1083

UE5接入在线直播视频源,如hls(m3u8)格式

UE5接入在线直播视频源

专注GIS开发 9503

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

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

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

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

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

SIMATIC S7-1200, S7-1500 PID 控制[手册]

SIMATIC S7-1200, S7-1500 PID 控制[手册]

HDU-3567 Eight II

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

wl16wzl的博客 319

Eight II HDU - 3567

Eight II HDU - 3567 知识点: bfs 打表, 康托展开 思路: 先预处理"X12345678",“1X2345678”,“12X345678”,“123X45678”,“1234X5678”,“12345X678”, “123456X78”,“1234567X8”,"12345678X"等状态 每次将给定的s1映射为9个状态中的一个x1,将s2通过s1到x1的映射得到目标状态x2,再根据打表得到答案即可 使用康托展开为了压缩空间 #include <iostream&gt

weixin_45535709的博客 219

hdu 3567 EightⅡ(映射+bfs暴力打表)

思路:跟hdu 1043 其实差不多,只是最后的状态变成了非唯一情况;我们要做的就是把最后的状态变成唯一的或者唯几的情况; 看了网上大佬的思路之后发现,不管最后的状态怎么变化,都可以映射成9种,也就是X放在其中的9个位置,然后按照映射关系把起始状态也映射一下,最后两个映射的达到路径跟要求的路径其实是一样的(虽然不知道为什么,但是事实如此); 因为有9种情况,那么就有9张表分别代表到达9个末位置...

摆渡人的博客 507

hdu3567 Eight II 康拓展开+打表+路径回溯+映射

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3567 题意:给你一个八数码的起始和终止状态,让你打印路径,要求字典序最小,长度最短,保证输入数据必有解。思路:2000ms 200组数据,平均10ms一组数据。用A*的话,可能会tle,而且还不能保证字典序最小。所以直接打表,考虑到起点,终点不定,所以需要映射,比如我把起点564178X23映射成1

AcmLzq的博客 1449

HDU 3567 Eight II (搜索)

题意:给出两个状态的八数码,问输出第一个状态转移到第二个状态的满足以下条件的方案 1.步骤最少 2.字典序最小如果直接进行转移,有几个很明显的问题,一时间不足,二如果双向BFS字典序不好处理,但是由于这道题的特殊性,我们只需要从一个状态转移到另一个状态,假设第一个输入为初状态,可以归纳为九类:012345678,102345678,120345678,123045678,123405678,12

每一次AC都是一种感动 854

HDU 3567 - Eight II 这该死的题

关于这道题 我真的想骂娘(好吧是自己太菜了) 我很早其实自己推出来了,就是还是bfs+康托但是列举九种不同的X位置,同时利用映射,注意要映射第一个输入的模板,然后倒序输出路径!!很重要 我一开始天真的想用路径urld然后顺序输出 然后- - 也就几个小时没了吧小问题 但是我卡在了两个莫名其妙的问题上 ** 康拓展开后面return忘记+1**,导致字典序在实例 5742631X8 1568...

Leslie5205912的博客 382

HDU 3567 Eight II (A*)

题目链接:Eight II 解析:还是八数码问题,当然还是A*了,只不过这次要加上预处理才行。 先枚举出‘X’的位置,然后用前驱表保存所有情况 然后直接回溯就行了,不用再搜了。 AC代码: #include #include #include #include #include #include #include using namespac

sxk 1447

HDU 3567 BFS+预处理

HDU 1043的加强版 8数码问题 给出8数码问题的两种状态,求从A状态到B状态的最优解,数据保证有解,若有多解,输出最短且字典序最小的。 基本思路和1043的差不多,只不过这次要预处理出来9种情况的BFS 即:     BFS(0,"012345678");     BFS(1,"102345678");     BFS(2,"120345678");     BFS(

803

hdu 3567 Eight II 八数码 双向BFS

代码:

冷月之殇 3390
上一篇: Educational Codeforces Round 59 (Rated for Div. 2) D Compression 【dp】
下一篇: HDU - 3533 Escape 【BFS】
Y390d
博客等级 码龄9年 11粉丝 165原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值