[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对象排序(Comparable)详细实例
对象实现Comparable接口 public class Field implements Comparable<Field>{ private String name; private ...
- SpringCloud学习笔记(5):Hystrix Dashboard可视化监控数据
简介 上篇文章中讲了使用Hystrix实现容错,除此之外,Hystrix还提供了近乎实时的监控.本文将介绍如何进行服务监控以及使用Hystrix Dashboard来让监控数据图形化. 项目介绍 sc ...
- HBase 超详细介绍
1-HBase的安装 HBase是什么? HBase是Apache Hadoop中的一个子项目,Hbase依托于Hadoop的HDFS作为最基本存储基础单元,通过使用hadoop的DFS工具就可以看到 ...
- PHP 扩展开发初探
什么是 PHP 扩展 通俗说,PHP 扩展是增强 PHP 语言功能的插件.PHP 提供了编程语言的语法,比如分支.循环.函数.类等,这些是 PHP 本身所提供的.在某些情况下需要在 PHP 语言的基础 ...
- Mybatis多数据源读写分离(注解实现)
#### Mybatis多数据源读写分离(注解实现) ------ 首先需要建立两个库进行测试,我这里使用的是master_test和slave_test两个库,两张库都有一张同样的表(偷懒,喜喜), ...
- 25 (OC)* iOS网络HTTP、TCP、UDP、Socket 知识总结
应用层:1.用户接口.应用程序:2.Application典型设备:网关:3.典型协议.标准和应用:TELNET.FTP.HTTP 表示层:1.数据表示.压缩和加密presentation2.典型设备 ...
- 零基础快速入门Java的秘诀
刚开始学习Java时要端正自己的学习的目标和态度,明确学习Java基础重点要做什么. 首先第一点,Java基础的学习,基础很重要,基础好地基牢,才能爬的高! 大家要从以下4个方向努力: 代码能力:一定 ...
- RestClient火狐接口测试
一.RestClient的简单介绍 RESTClient是一款用于测试各种Web服务的插件,它可以向服务器发送各种HTTP请求(用户也可以自定义请求方式),并显示服务器响应.二.RESTClient的 ...
- phpStudy后门漏洞利用复现
phpStudy后门漏洞利用复现 一.漏洞描述 Phpstudy软件是国内的一款免费的PHP调试环境的程序集成包,通过集成Apache.PHP.MySQL.phpMyAdmin.ZendOptimiz ...
- ajax跨域访问数据
通过json发送和接受数据,数据以json的格式在服务器端和前台进行传递,什么是json数据?这里就不进行详细阐述,轻自行百度解决. 在html5 中利用ajax 异步请求时,会遇到跨域的问题,如果域 ...