[luogu]P1379 八数码难题[广度优先搜索]
八数码难题
——!x^n+y^n=z^n
我在此只说明此题的一种用BFS的方法,因为本人也是初学,勉勉强强写了一个单向的BFS,据说最快的是IDA*(然而蒟蒻我不会…)
各位如果想用IDA*的可以看看这位大佬的这篇文章:
http://www.cnblogs.com/ZYBGMZL/p/6852733.html
接下来是我的方法,用luogu的跑了最慢是200ms,感觉还行把。
题目描述
在3×3的棋盘上,摆有八个棋子,每个棋子上标有1至8的某一数字。棋盘中留有一个空格,空格用0来表示。空格周围的棋子可以移到空格中。要求解的问题是:给出一种初始布局(初始状态)和目标布局(为了使题目简单,设目标状态为123804765),找到一种最少步骤的移动方法,实现从初始布局到目标布局的转变。
输入输出格式
输入格式:
输入初试状态,一行九个数字,空格用0表示
输出格式:
只有一行,该行只有一个数字,表示从初始状态到目标状态需要的最少移动次数(测试数据中无特殊无法到达目标状态数据)
输入输出样例
输入样例#1:
283104765
输出样例#1:
4
因为这是要最优解且保证数据有解,于是就想到了BFS。
然而这个过程是有许多障碍的,要怎样检验自己的状态是否为解,还有判重的操作,如果你没有判重,TLE即在眼前…
所以我们可以想到压缩状态!当然如果用二进制难免有点力不从心,那我们干脆存成整数不就行了?但是可能你会发现,会有前导零的情况,怎么办?
这时候其实可以在状态前加一个1,在int型中还是过得去的。
那判重怎么搞?注意到这只有9!种状态。
想到什么?康托尔展开!对于0~8的全排列,
012345678 的字典序是1,如果让你手动操作我想没什么问题,那怎么让计算机做这件事?
对于 (a(n-1) a(n-2)L a(0))的字典序计算方法为:
Σ(ci*i!)ci为当前未出现的比ai小的数的个数。
既然这样,我们就能把状态一一存下来了,交换的话很简单,读者手动操作即可发现规律。
简单说明之后附上代码参考一下:
- #include<iostream>
- #include<cstdio>
- #include<cstring>
- using namespace std;
- #define maxn 400000
- //阶乘?我当然打表啦。
- ]={,,,,,,,,,};
- //状态
- struct sjs{
- int num;
- int pos;
- }state[maxn];
- //队列
- struct _757{
- int time;
- int now;
- int fd;
- }qu[maxn];
- ];
- //判重
- bool rep[maxn];
- int head,tail;
- //特殊嗜好???
- namespace lys{
- //快速幂
- int fpow(int p){
- ,;
- ){
- ) res*=base;
- base*=base;
- p>>=;
- }
- return res;
- }
- //计算cantor
- int cantor(int num){
- ,pos,res=;
- int x=num;
- memset(cto,,sizeof cto);
- ){
- cto[i]=num%;
- ) pos=i;
- num/=;
- i++;
- }
- int j,cal;
- ;i>=;i--){
- cal=;
- ;j>i;j--){
- if(cto[j]<cto[i]) cal++;
- }
- res+=(cto[i]-cal)*fac[i];
- }
- state[res+].num=x;
- state[res+].pos=pos;
- ;
- }
- //判断是否能移动
- bool chk(int pos,int i){
- switch(i){
- :) return true ; return false ;
- :) return true ; return false ;
- :||pos==||pos==) return false ; return true ;
- :||pos==||pos==) return false ; return true ;
- }
- }
- int bfs(){
- ,i,st,ch,fp,x,num;
- do{
- st=qu[head].now;
- fp=fpow(state[st].pos);
- num=state[st].num;
- ;i<=;i++){
- if(chk(state[st].pos,i)){
- switch(i){
- :
- x=(num/(fp*))%;
- ch=num-x*fp*+x*fp;
- x=cantor(ch);
- qu[++tail].now=x;
- qu[tail].time=(qu[head].time+);
- qu[tail].fd=head;
- //目标态,觉得不这样写也行,直接用num比较
- ){
- return qu[tail].time;
- }
- if(rep[x]) tail--;
- else rep[x]=true ;
- break ;
- :
- x=(num/(fp/))%;
- ch=num-x*fp/+x*fp;
- x=cantor(ch);
- qu[++tail].now=x;
- qu[tail].time=(qu[head].time+);
- qu[tail].fd=head;
- ){
- return qu[tail].time;
- }
- if(rep[x]) tail--;
- else rep[x]=true ;
- break ;
- :
- x=(num/(fp*))%;
- ch=num+x*fp-x*fp*;
- x=cantor(ch);
- qu[++tail].now=x;
- qu[tail].time=(qu[head].time+);
- qu[tail].fd=head;
- ){
- return qu[tail].time;
- }
- if(rep[x]) tail--;
- else rep[x]=true ;
- break ;
- :
- x=(num/(fp/))%;
- ch=num+x*fp-x*fp/;
- x=cantor(ch);
- qu[++tail].now=x;
- qu[tail].time=(qu[head].time+);
- qu[tail].fd=head;
- ){
- return qu[tail].time;
- }
- if(rep[x]) tail--;
- else rep[x]=true ;
- break ;
- }
- }
- }
- head++;
- }while(head<=tail);
- }
- int main(){
- int i,j;
- char c;
- ;
- ;i<=;i++){
- ;j<=;j++){
- c=getchar();
- ') c=getchar();
- st=st*+c-';
- }
- }
- //初始状态
- +st);
- qu[++head].now=r;
- qu[head].time=;
- rep[r]=true ;
- tail=;
- printf("%d\n",bfs());
- ;
- }
- }
- int main(){
- lys::main();
- ;
- }
[luogu]P1379 八数码难题[广度优先搜索]的更多相关文章
- luogu P1379 八数码难题
题目描述 在3×3的棋盘上,摆有八个棋子,每个棋子上标有1至8的某一数字.棋盘中留有一个空格,空格用0来表示.空格周围的棋子可以移到空格中.要求解的问题是:给出一种初始布局(初始状态)和目标布局(为了 ...
- luogu P1379 八数码难题(A*算法入门详细讲解)
代码实现细节 #include<cstdio> #include<cstring> #include<iostream> using namespace std; ...
- 洛谷 P1379 八数码难题 解题报告
P1379 八数码难题 题目描述 在3×3的棋盘上,摆有八个棋子,每个棋子上标有1至8的某一数字.棋盘中留有一个空格,空格用0来表示.空格周围的棋子可以移到空格中.要求解的问题是:给出一种初始布局(初 ...
- 洛谷——P1379 八数码难题
P1379 八数码难题 双向BFS 原来双向BFS是这样的:终止状态与起始状态同时入队,进行搜索,只不过状态标记不一样而已,本题状态使用map来存储 #include<iostream> ...
- 洛谷P1379八数码难题
题目描述 在3×3的棋盘上,摆有八个棋子,每个棋子上标有1至8的某一数字.棋盘中留有一个空格,空格用0来表示.空格周围的棋子可以移到空格中. 要求解的问题是:给出一种初始布局(初始状态)和目标布局(为 ...
- codevs1225八数码难题(搜索·)
1225 八数码难题 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 钻石 Diamond 题解 题目描述 Description Yours和zero在研究A*启 ...
- 洛谷—— P1379 八数码难题
https://daniu.luogu.org/problem/show?pid=1379 题目描述 在3×3的棋盘上,摆有八个棋子,每个棋子上标有1至8的某一数字.棋盘中留有一个空格,空格用0来表示 ...
- 洛谷 P1379 八数码难题
题目描述 在3×3的棋盘上,摆有八个棋子,每个棋子上标有1至8的某一数字.棋盘中留有一个空格,空格用0来表示.空格周围的棋子可以移到空格中.要求解的问题是:给出一种初始布局(初始状态)和目标布局(为了 ...
- 洛谷 - P1379 - 八数码难题 - bfs
https://www.luogu.org/problemnew/show/P1379 #include <bits/stdc++.h> using namespace std; #def ...
随机推荐
- Centos 环境一键部署脚本(shell脚本)
谨以此文纪念吊炸天的Centos环境一键部署方案的新鲜出炉 辛苦大半年,产品准备上线了,BOSS亲自体验安装部署,看着超过200+页的安装文档直接崩溃了(需要部署23个基础服务),经历了超过3个小时的 ...
- Hadoop的编译
Hadoop2.4.0 重新编译 64 位本地库 原创作者:大鹏鸟 时间:2014-07-28 环境:虚拟机 VirtualBox,操作系统 64 位 CentOS 6.4 下载重新编译需要的软件 ...
- [0] C#实现WebBrowser&HTML交互
using System;using System.ComponentModel;using System.Windows.Forms; namespace WindowsApplication5{ ...
- scrapy代理的设置
scrapy代理的设置 在我的上一篇文章介绍了scrapy下载器中间件的使用,这里的scrapyIP的代理就是用这个原理实现的,重写了下载器中间件的process_request(self,reque ...
- qt中setStyleSheet导致的内存泄漏
原始日期: 2017-01-05 19:31 现象:程序运行至某一个界面下,内存出现缓慢持续的占用内存增长 原因:经过排查,确定是在事件派发的槽函数中频繁重复调用setStyleSheet导致的 ...
- Index Scans 索引扫描
官方文档链接地址 http://docs.oracle.com/cd/E11882_01/server.112/e40540/indexiot.htm#CNCPT1170 Index Scans 在索 ...
- 二维码生成api
<img id='qrcode_img' src='http://qr.liantu.com/api.php?text={$wenzi}&w={$width}' /> http:/ ...
- 【Android Developers Training】 17. 停止和重启一个Activity
注:本文翻译自Google官方的Android Developers Training文档,译者技术一般,由于喜爱安卓而产生了翻译的念头,纯属个人兴趣爱好. 原文链接:http://developer ...
- 4.jsp的内置对象
1.jsp有九大内置对象 out request response session application page pagecontext exception config 2.用户发请求 requ ...
- HTML5 进阶系列:文件上传下载
前言 HTML5 中提供的文件API在前端中有着丰富的应用,上传.下载.读取内容等在日常的交互中很常见.而且在各个浏览器的兼容也比较好,包括移动端,除了 IE 只支持 IE10 以上的版本.想要更好地 ...