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

HDU3567):八数码问题(升级版)——双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;
}

 

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

相关推荐

数控弯管机xyz转换ybc的算法_花了一年时间开发的三维弯管机交互式转档软件(三维管子模型UG,SOLIDWORK,PRO/E文件转成YBC)...

在弯管机加工中,由管子模型生成可直接进行弯管加工的YBC数据可以大大提高弯管编程过程.传统的做法是先用dxf数据文件(用autocad绘制管子的轴心线数据)转出XYZ数据,然后由XYZ数据转成YBC数据,而且大部分厂家对文件版本以及软件做管方式都有不少限制,这大大花费了用户的时间跟精力.随着企业的信息化管理以及不断的技术升级,传统用autocad线条模式来描述管子的方式正在被用户用PRO/E,UG...

weixin_29065959的博客 1913

hdu 3567(八码数 + 双向bfs

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

积少成多,水滴石穿 651

【生产实践】PostgreSQL高可用Patroni安装(超详细已踩坑)

一 安装Patroni 0 Patroni 对Python的版本要求 我安装的是Patroni最新版本 :4.0.3,Patroni 对Python 版本有要求,没有具体的版本矩阵,但是根据每个版本发布信息可以得到以下信息 Patroni 4.0 需要 Python 3.8 以上(可以根据下面发布版本信息推理出) Version 3.0.2 Version 3.0.2 dropped support of Python older than 3.6. 版本3.0.2不再支持3.6版本以下的P

DBA之路的博客 1695

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_的博客 1093

hdu 3567(八数码问题 双向BFS

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

m0_37514283的博客 1592

HDU - 3567 Eight II(IDA*)

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

qq_43586463的博客 270

Eight II HDU - 3567bfs打表+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的博客 1081

HDU 3567 Eight IIBFS+映射+康托展开

题面 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的博客 1024

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的博客 284

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的博客 272

HDU 3567 BFS+预处理

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

802

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

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

摆渡人的博客 504

hdu 1430+hdu 3567(预处理)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1430 思路:由于只是8种颜色,所以标号就无所谓了,对起始状态重新修改标号为 12345678,对目标状态标号做相应的修改,先预处理出12345678到所有状态的路径,记录所有状态的pre值,直接输出即可。 1 #include&lt;iostream&gt; 2 #include...

weixin_34265814的博客 153

HDU 3567 - Eight II

B - Eight II Time Limit:2000MS     Memory Limit:65536KB     64bit IO Format:%I64d & %I64u Submit Status Practice HDU 3567 Appoint description:  System Crawler  (2016-01-18) Descriptio

里弗杰克 680

HDU3567Eight 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!荣耀之路! 4941

HDU 3567 Eight II

Eight II Time Limit: 2000ms Memory Limit: 65536KB This problem will be judged onHDU. Original ID:356764-bit integer IO format:%I64d Java class name:Main Eight-puzzle, which is...

weixin_30482181的博客 324

hdu 3567 康托展开 +BFS

HDU 1430 DFS + 康托展开 + 映射处理 +预处理! http://blog.csdn.net/little_boy_z/article/details/78428300 和hdu1430很类似,模仿着来即可。 主要会用康托就好了 #include #include #include #include #include #include #inc

Little_boy_z的博客 383

hdu3567 双向BFS

太感人了,错了一天看了一天,终于AC了! 仿佛人生度过了几个轮回呜呜呜 这题,看题解都是双向BFS,因为双向比单向快了好多 双向,说白就是一键双开,让你在开前面的时候顺便开后面,用两个队列也行,一个队列更好写,因为你得开完两个队列前面一层再开后面一层,你只要用一个 flag标记一下前后即可 1. 然后正向与反向有什么区别呢,正向遇到反向的最小,才是最小,而反向的最小遇到正向,此时不一定是最小 例如题目的顺序是 dlru 那么你两边都是从dlru那么走, 假设你的后面走了dl 忽然发现前面有一个u刚好可以,

qq_37548017的博客 333

[BFS + 打表] HDU 3567

先枚举X不同位置的9种方案,用bfs搜出这种方案到其他所有方案的移动方法

Aria461863631的博客 402

hdu3567 Eight II(IDA*+康托展开)

题目链接:点击打开链接 题意描述:经典八数码问题,给定起始状态和目标状态,经过d、l、r、u移动,求解如何移动能使起始状态到达目标状态? 1、移动的次数尽可能少 2、如果移动次数相同,求解移动序列的最小字典序? 解题思路:典型的IDA*题目 估值函数:从当前状态移动到目标状态所需的最小步数(我们可以通过曼哈顿距离进行估值),用于剪枝 迭代:此处我们不再使深度每次加1,而是在搜索

Crazy_Bear 978

apple苹果寻物airtag真实模型拆解高度复现stp三维3D仿真模型.stp

结构文件在此,结构图形见:https://blog.csdn.net/qq_26164991/article/details/118250747apple苹果findmy寻物airtag真实模型拆解高度复现stp三维3D仿真模型,可用于仿真

上一篇: Educational Codeforces Round 59 (Rated for Div. 2) D Compression 【dp】
下一篇: HDU - 3533 Escape 【BFS】
Y390d
博客等级 码龄9年 11粉丝 165原创
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值