[Luogu1379]八数码难题
题目描述
在3×3的棋盘上,摆有八个棋子,每个棋子上标有1至8的某一数字。棋盘中留有一个空格,空格用0来表示。空格周围的棋子可以移到空格中。要求解的问题是:给出一种初始布局(初始状态)和目标布局(为了使题目简单,设目标状态为123804765),找到一种最少步骤的移动方法,实现从初始布局到目标布局的转变。
输入输出格式
输入格式:
输入初始状态,一行九个数字,空格用0表示
输出格式:
只有一行,该行只有一个数字,表示从初始状态到目标状态需要的最少移动次数(测试数据中无特殊无法到达目标状态数据)
输入输出样例
283104765
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]八数码难题的更多相关文章
- 双向广搜+hash+康托展开 codevs 1225 八数码难题
codevs 1225 八数码难题 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 钻石 Diamond 题目描述 Description Yours和zero在研究A*启 ...
- Codevs 1225 八数码难题
1225 八数码难题 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 钻石 Diamond 题目描述 Description Yours和zero在研究A*启发式算法.拿到一道经典的 ...
- [luogu]P1379 八数码难题[广度优先搜索]
八数码难题 ——!x^n+y^n=z^n 我在此只说明此题的一种用BFS的方法,因为本人也是初学,勉勉强强写了一个单向的BFS,据说最快的是IDA*(然而蒟蒻我不会…) 各位如果想用IDA*的可以看看 ...
- 洛谷P1379八数码难题
题目描述 在3×3的棋盘上,摆有八个棋子,每个棋子上标有1至8的某一数字.棋盘中留有一个空格,空格用0来表示.空格周围的棋子可以移到空格中. 要求解的问题是:给出一种初始布局(初始状态)和目标布局(为 ...
- 洛谷 P1379 八数码难题 解题报告
P1379 八数码难题 题目描述 在3×3的棋盘上,摆有八个棋子,每个棋子上标有1至8的某一数字.棋盘中留有一个空格,空格用0来表示.空格周围的棋子可以移到空格中.要求解的问题是:给出一种初始布局(初 ...
- 【洛谷P1379】八数码难题(广搜、A*)
八数码难题 题目描述 一.广搜: 首先要考虑用什么存每一个状态 显然每个状态都用一个矩阵存是很麻烦的. 我们可以考虑将一个3*3的矩阵用一个字符串或long long 存. 每次扩展时再转化为矩阵. ...
- 习题:八数码难题(双向BFS)
八数码难题(wikioi1225) [题目描述] 在3×3的棋盘上,摆有八个棋子,每个棋子上标有1至8的某一数字.棋盘中留有一个空格,空格用0来表示.空格周围的棋子可以移到空格中.要求解的问题是:给出 ...
- 「LuoguP1379」 八数码难题(迭代加深
[P1379]八数码难题 - 洛谷 题目描述 在3×3的棋盘上,摆有八个棋子,每个棋子上标有1至8的某一数字.棋盘中留有一个空格,空格用0来表示.空格周围的棋子可以移到空格中.要求解的问题是:给出一种 ...
- 洛谷——P1379 八数码难题
P1379 八数码难题 双向BFS 原来双向BFS是这样的:终止状态与起始状态同时入队,进行搜索,只不过状态标记不一样而已,本题状态使用map来存储 #include<iostream> ...
随机推荐
- 弄懂Java为何只有值传递
最近有同学问我关于Java中值传递与引用传递的问题,在此小结一下 值传递是指在函数调用时将实参内容复制一份传递给形参,这样在函数中改变该参数不会对原参数产生影响. 引用传递是指将对象地址的引用传递给该 ...
- 03 (H5*) Vue第三天
目录: 1:Vue-resource中的全局配置. 2:Vue动画2部曲 3:animate动画 4:钩子函数动画 5:组件三部曲,推荐使用template标签来创建组件模板 1:Vue-resour ...
- 让tomcat使用指定JDK
一,前言 我们都知道,tomcat启动前需要配置JDK环境变量,如果没有配置JDK的环境变量,那么tomcat启动的时候就会报错,也就是无法启动. 但是在我们的工作或者学习过程中,有的时候会出现tom ...
- 四、springBoot 优雅的创建定时任务
前言 好几天没写了,工作有点忙,最近工作刚好做一个定时任务统计的,所以就将springboot 如何创建定时任务整理了一下. 总的来说,springboot创建定时任务是非常简单的,不用像spring ...
- Java匹马行天下之 Java国出了个Java——举国欢庆
Java帝国的崛起 前言: 看庭前花开花落,宠辱不惊, 望天上云卷云舒,去留无意. 闹心的事儿,选择释怀: 纠缠的人儿,试着放下, 生活其实很美. 心若向阳,就无惧悲伤. 愿你明朗坦荡纵情豁达,有得有 ...
- SPSS学习笔记参数检验—单样本t检验
单样本t检验 目的:利用来自总体的样本数据,推断该总体的均值是否与指定的检验值存在差异. 适用条件:样本来自的总体应服从或者近似服从正态分布. 注:当样本量n比较大时:由中心极限定理得知,即使原数据不 ...
- Spring Boot 整合视图层技术
这一节我们主要学习如何整合视图层技术: Jsp Freemarker Thymeleaf 在之前的案例中,我们都是通过 @RestController 来处理请求,所以返回的内容为json对象.那么如 ...
- 使用 .NET Core 3.0 的 AssemblyLoadContext 实现插件热加载
一般情况下,一个 .NET 程序集加载到程序中以后,它的类型信息以及原生代码等数据会一直保留在内存中,.NET 运行时无法回收它们,如果我们要实现插件热加载 (例如 Razor 或 Aspx 模版的热 ...
- Shell之操作环境
目录 Shell之操作环境 参考 命令运行顺序 欢迎信息 环境配置 Shell之操作环境
- 关于Python selenium实现类似比价软件的功能
偶然间想实现比价的功能,正常requests途径比较难实现,于是乎想到可以selenium可以简易实现,下面是代码. import requests from selenium import webd ...