题目描述

在3×3的棋盘上,摆有八个棋子,每个棋子上标有1至8的某一数字。棋盘中留有一个空格,空格用0来表示。空格周围的棋子可以移到空格中。要求解的问题是:给出一种初始布局(初始状态)和目标布局(为了使题目简单,设目标状态为123804765),找到一种最少步骤的移动方法,实现从初始布局到目标布局的转变。

输入输出格式

输入格式:

输入初始状态,一行九个数字,空格用0表示

输出格式:

只有一行,该行只有一个数字,表示从初始状态到目标状态需要的最少移动次数(测试数据中无特殊无法到达目标状态数据)

输入输出样例

输入样例#1:

283104765
输出样例#1:

4


普通搜索7000ms
#include <cstdio>
#include <iostream>
#include <queue>
#include <map>
using namespace std;
#define reg register
#define ll long long
ll St, Ed;
map<ll, int> vis;
struct date {
ll hsh;
int stp;
};
const int dx[] = {, , -, , }, dy[] = {, , , , -};
int main()
{
scanf("%lld", &St);
Ed = ;
queue <date> q;
q.push((date){St, });
while(!q.empty())
{
ll hsh = q.front().hsh;
int tp = q.front().stp;
q.pop();
if (hsh == Ed) {
printf("%d\n", tp);
return ;
}
int a[][];
int tmp = hsh;
for (reg int i = ; i >= ; i --)
for (reg int j = ; j >= ; j --)
a[i][j] = tmp % , tmp /= ;
int x = , y = ;
for (reg int i = ; i <= ; i ++)
for (reg int j = ; j <= ; j ++)
if (!a[i][j]) {x = i, y = j;break;}
for (reg int i = ; i <= ; i ++)
{
int tx = x + dx[i], ty = y + dy[i];
if (tx <= or tx > or ty <= or ty > ) continue;
swap(a[x][y], a[tx][ty]);
int nhsh = ;
for (reg int i = ; i <= ; i ++)
for (reg int j = ; j <= ; j ++)
nhsh = nhsh * + a[i][j];
if (!vis[nhsh]) vis[nhsh] = , q.push((date){nhsh, tp + });
swap(a[x][y], a[tx][ty]);
}
}
return ;
}

双向广搜242ms

#include <cstdio>
#include <iostream>
#include <queue>
#include <map>
using namespace std;
#define reg register
#define ll long long
ll St, Ed;
map<ll, int> vis1, vis2;
struct date {
ll hsh;
int stp;
};
const int dx[] = {, , -, , }, dy[] = {, , , , -};
int main()
{
scanf("%lld", &St);
Ed = ;
queue <date> q1, q2;
q1.push((date){St, });
q2.push((date){Ed, });
vis1[St] = , vis2[Ed] = ;
if (St == Ed) return puts(""), ;
while(!q1.empty() and !q2.empty())
{
ll hsh = q1.front().hsh;
int tp = q1.front().stp;
q1.pop();
if (vis2[hsh]) {
printf("%d\n", tp + vis2[hsh]);
return ;
}
int a[][];
int tmp = hsh;
for (reg int i = ; i >= ; i --)
for (reg int j = ; j >= ; j --)
a[i][j] = tmp % , tmp /= ;
int x = , y = ;
for (reg int i = ; i <= ; i ++)
for (reg int j = ; j <= ; j ++)
if (!a[i][j]) {x = i, y = j;break;}
for (reg int i = ; i <= ; i ++)
{
int tx = x + dx[i], ty = y + dy[i];
if (tx <= or tx > or ty <= or ty > ) continue;
swap(a[x][y], a[tx][ty]);
int nhsh = ;
for (reg int i = ; i <= ; i ++)
for (reg int j = ; j <= ; j ++)
nhsh = nhsh * + a[i][j];
if (!vis1[nhsh]) vis1[nhsh] = tp + , q1.push((date){nhsh, tp + });
swap(a[x][y], a[tx][ty]);
}
hsh = q2.front().hsh;
tp = q2.front().stp;
q2.pop();
if (vis1[hsh]) {
printf("%d\n", tp + vis1[hsh]);
return ;
}
tmp = hsh;
for (reg int i = ; i >= ; i --)
for (reg int j = ; j >= ; j --)
a[i][j] = tmp % , tmp /= ;
x = , y = ;
for (reg int i = ; i <= ; i ++)
for (reg int j = ; j <= ; j ++)
if (!a[i][j]) {x = i, y = j;break;}
for (reg int i = ; i <= ; i ++)
{
int tx = x + dx[i], ty = y + dy[i];
if (tx <= or tx > or ty <= or ty > ) continue;
swap(a[x][y], a[tx][ty]);
int nhsh = ;
for (reg int i = ; i <= ; i ++)
for (reg int j = ; j <= ; j ++)
nhsh = nhsh * + a[i][j];
if (!vis2[nhsh]) vis2[nhsh] = tp + , q2.push((date){nhsh, tp + });
swap(a[x][y], a[tx][ty]);
}
}
return ;
}

[Luogu1379]八数码难题的更多相关文章

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

    codevs 1225 八数码难题  时间限制: 1 s  空间限制: 128000 KB  题目等级 : 钻石 Diamond   题目描述 Description Yours和zero在研究A*启 ...

  2. Codevs 1225 八数码难题

    1225 八数码难题 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 钻石 Diamond 题目描述 Description Yours和zero在研究A*启发式算法.拿到一道经典的 ...

  3. [luogu]P1379 八数码难题[广度优先搜索]

    八数码难题 ——!x^n+y^n=z^n 我在此只说明此题的一种用BFS的方法,因为本人也是初学,勉勉强强写了一个单向的BFS,据说最快的是IDA*(然而蒟蒻我不会…) 各位如果想用IDA*的可以看看 ...

  4. 洛谷P1379八数码难题

    题目描述 在3×3的棋盘上,摆有八个棋子,每个棋子上标有1至8的某一数字.棋盘中留有一个空格,空格用0来表示.空格周围的棋子可以移到空格中. 要求解的问题是:给出一种初始布局(初始状态)和目标布局(为 ...

  5. 洛谷 P1379 八数码难题 解题报告

    P1379 八数码难题 题目描述 在3×3的棋盘上,摆有八个棋子,每个棋子上标有1至8的某一数字.棋盘中留有一个空格,空格用0来表示.空格周围的棋子可以移到空格中.要求解的问题是:给出一种初始布局(初 ...

  6. 【洛谷P1379】八数码难题(广搜、A*)

    八数码难题 题目描述 一.广搜: 首先要考虑用什么存每一个状态 显然每个状态都用一个矩阵存是很麻烦的. 我们可以考虑将一个3*3的矩阵用一个字符串或long long 存. 每次扩展时再转化为矩阵. ...

  7. 习题:八数码难题(双向BFS)

    八数码难题(wikioi1225) [题目描述] 在3×3的棋盘上,摆有八个棋子,每个棋子上标有1至8的某一数字.棋盘中留有一个空格,空格用0来表示.空格周围的棋子可以移到空格中.要求解的问题是:给出 ...

  8. 「LuoguP1379」 八数码难题(迭代加深

    [P1379]八数码难题 - 洛谷 题目描述 在3×3的棋盘上,摆有八个棋子,每个棋子上标有1至8的某一数字.棋盘中留有一个空格,空格用0来表示.空格周围的棋子可以移到空格中.要求解的问题是:给出一种 ...

  9. 洛谷——P1379 八数码难题

    P1379 八数码难题 双向BFS 原来双向BFS是这样的:终止状态与起始状态同时入队,进行搜索,只不过状态标记不一样而已,本题状态使用map来存储 #include<iostream> ...

随机推荐

  1. SpringCloud学习笔记(6):使用Zuul构建服务网关

    简介 Zuul是Netflix提供的一个开源的API网关服务器,SpringCloud对Zuul进行了整合和增强.服务网关Zuul聚合了所有微服务接口,并统一对外暴露,外部客户端只需与服务网关交互即可 ...

  2. Linux下Eclipse以及Java环境安装教程[小白化](2019-9)

    Linux下安装Eclipse以及Java 一.前言 许久未用Eclipse, Ubuntu上也没装Eclipse, 今天安装发现, 好多东西都忘了. 不过经过一番查找(百度, csdn) 终于还是安 ...

  3. day 12 特殊权限

    1.suid (set uid) 特殊权限 suid优点: 可以让普通用户执行无法执行的命令 方便 suid缺点: 如果rm 为suid, 无论谁执行该命令,都能删除系统的任何 资源 set uid ...

  4. MOOC 数据库系统笔记(二):数据库系统的基本结构及其演变发展

    数据库系统的结构抽象与演变 数据库的标准结构 DBMS管理数据的三个层次 1.External Level = User Level 某一用户能够看到与处理的数据,全局数据中的某一部分 2.Conce ...

  5. Spring Cloud异步场景分布式事务怎样做?试试RocketMQ

    一.背景 在微服务架构中,我们常常使用异步化的手段来提升系统的 吞吐量 和 解耦 上下游,而构建异步架构最常用的手段就是使用 消息队列(MQ),那异步架构怎样才能实现数据一致性呢?本文主要介绍如何使用 ...

  6. js屏蔽地区

    其实不需要后台代码也可以获取地区信息的,就算是后台代码,也得需要引用一些第三方库提供免费的api接口才可以,最后还是反序列化才能得到想要的数据,那干嘛不直接找,提供好json格式的api接口,拿来js ...

  7. linux虚拟化简介

    为跨平台而生 在计算机发展的早期,各类计算平台.计算设备所提供的接口.调用方式纷繁复杂,没有像今天这样相对统一的标准.由于需要适配不同的平台,需要写很多繁琐的兼容代码,这无形中给开发者带来了很大的不便 ...

  8. 2018年蓝桥杯java b组第七题

    标题:螺旋折线 如图p1.pgn所示的螺旋折线经过平面上所有整点恰好一次. 对于整点(X, Y),我们定义它到原点的距离dis(X, Y)是从原点到(X, Y)的螺旋折线段的长度. 例如dis(0, ...

  9. 格子游戏Grid game CodeForce#1104C 模拟

    题目链接:Grid game 题目原文 You are given a 4x4 grid. You play a game — there is a sequence of tiles, each o ...

  10. Gitlab+Gitlab-CI+Docker实现持续集成(CI)与持续部署(CD)

    写在前面 记录一下,一个自动化开发部署项目的构建过程与简单使用,实现真正的DevOps gitlab安装 步骤一:安装依赖 yum -y install git gcc glibc-static te ...