双向bfs-八数码问题
[八数码][1]
[1]: https://www.luogu.org/problem/show?pid=1379
其实除了搜索恶心一点,好像也没什么提高+的
bfs搜的是状态。
双向bfs同时从起点(初始状态)和终点(最终状态)开始搜。当两边搜到同样的状态说明出结果了。因为bfs是一层层搜的,所以最早搜到同样状态就是最优解。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<ctime>
#include<string>
#include<set>
#include<queue>
#include<vector>
using namespace std;
struct str
{
string s;//当前状态字符串
int posi;//当前状态0的位置
};
int fangxiang[]={-3,+1,+3,-1};//up right down left
//fangxiang[]预先储存好各个方向的运算数,直接把0的位置加上去就好
set <string> m1,m2;//set判断这个状态是否已经有了
queue <str> q1,q2;//queue是枚举的状态
int c,c1=1,c2=1,cc;//c为循环边界(由c1,c2)获得,c1是上次bfs得来的本次bfs的状态数
int bfs()
{
while(!q1.empty())
{
cc++;
str t,x;
//zheng
c=c1;
c1=0;
while(c--)
{
t=q1.front();
q1.pop();
for(int j=0;j<4;j++)
{
x=t;
//看下面,都差不多的
if(j==0 and t.posi<3)
continue;
if(j==1 and t.posi%3==2)
continue;
if(j==2 and t.posi>5)
continue;
if(j==3 and t.posi%3==0)
continue;
swap(x.s[x.posi],x.s[x.posi+fangxiang[j]]);
x.posi+=fangxiang[j];
if(m1.count(x.s))
continue;
q1.push(x);
c1++;
m1.insert(x.s);
if(m2.count(x.s))
return cc*2-1;
}
}
//fan
c=c2;
c2=0;
for(int i=0;i<c;i++)
{
t=q2.front();//取出队首,进行bfs
q2.pop();
for(int j=0;j<4;j++)
{
x=t;
//需要枚举4个方向,所以用个x
if(j==0 and t.posi<3)
continue;
if(j==1 and t.posi%3==2)
continue;
if(j==2 and t.posi>5)
continue;
if(j==3 and t.posi%3==0)
continue;
//限制条件
swap(x.s[x.posi],x.s[x.posi+fangxiang[j]]);//移动0
x.posi+=fangxiang[j];
if(m2.count(x.s))
continue;
q2.push(x);
c2++;
m2.insert(x.s);
if(m1.count(x.s))
return cc*2;
}
}
}
return 0;
}
int main()
{
//freopen("4.in","r",stdin);
ios::sync_with_stdio(false);
str ed=(str){"123804765",4};
str st;
cin>>st.s;
st.posi=st.s.find('0');
q1.push(st);
q2.push(ed);
m1.insert(st.s);
m2.insert(ed.s);
if(st.s==ed.s)//如果起始和终止相同,那太好了根本不用移!
{
cout<<"0";
return 0;
}
cout<<bfs();
return 0;
}
双向bfs-八数码问题的更多相关文章
- BFS(八数码) POJ 1077 || HDOJ 1043 Eight
题目传送门1 2 题意:从无序到有序移动的方案,即最后成1 2 3 4 5 6 7 8 0 分析:八数码经典问题.POJ是一次,HDOJ是多次.因为康托展开还不会,也写不了什么,HDOJ需要从最后的状 ...
- 习题:八数码难题(双向BFS)
八数码难题(wikioi1225) [题目描述] 在3×3的棋盘上,摆有八个棋子,每个棋子上标有1至8的某一数字.棋盘中留有一个空格,空格用0来表示.空格周围的棋子可以移到空格中.要求解的问题是:给出 ...
- 洛谷 P1379 八数码难题(map && 双向bfs)
题目传送门 解题思路: 一道bfs,本题最难的一点就是如何储存已经被访问过的状态,如果直接开一个bool数组,空间肯定会炸,所以我们要用另一个数据结构存,STL大法好,用map来存,直接AC. AC代 ...
- 双向广搜+hash+康托展开 codevs 1225 八数码难题
codevs 1225 八数码难题 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 钻石 Diamond 题目描述 Description Yours和zero在研究A*启 ...
- 【双向广搜+逆序数优化】【HDU1043】【八数码】
HDU上的八数码 数据强的一B 首先:双向广搜 先处理正向搜索,再处理反向搜索,直至中途相遇 visit 和 队列都是独立的. 可以用一个过程来完成这2个操作,减少代码量.(一般还要个深度数组) 优化 ...
- HDU1043 八数码(BFS + 打表)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1043 , 康托展开 + BFS + 打表. 经典八数码问题,传说此题不做人生不完整,关于八数码的八境界 ...
- HDU-1043 Eight八数码 搜索问题(bfs+hash 打表 IDA* 等)
题目链接 https://vjudge.net/problem/HDU-1043 经典的八数码问题,学过算法的老哥都会拿它练搜索 题意: 给出每行一组的数据,每组数据代表3*3的八数码表,要求程序复原 ...
- luoguP1379-八数码难题(双向bfs)
题目链接:https://www.luogu.org/problemnew/show/P1379 题意:用字符串表示八数码,求根据给定八数码得到末状态“123804765”最少的步数. 思路:这题很方 ...
- UVALive 6665 Dragonâs Cruller --BFS,类八数码问题
题意大概就是八数码问题,只不过把空格的移动方式改变了:空格能够向前或向后移动一格或三格(循环的). 分析:其实跟八数码问题差不多,用康托展开记录状态,bfs即可. 代码: #include <i ...
- [cdoj1380] Xiper的奇妙历险(3) (八数码问题 bfs + 预处理)
快要NOIP 2016 了,现在已经停课集训了.计划用10天来复习以前学习过的所有内容.首先就是搜索. 八数码是一道很经典的搜索题,普通的bfs就可求出.为了优化效率,我曾经用过康托展开来优化空间,甚 ...
随机推荐
- Leetcode题解(32)
107. Binary Tree Level Order Traversal II 题目 直接代码: /** * Definition for a binary tree node. * struct ...
- Ignatius and the Princess II
Ignatius and the Princess II Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Jav ...
- 附录三 关于book.h
本书中用到的公用函数放到了头文件book.h中. #ifndef __BOOK_H__ #define __BOOK_H__ #include <stdio.h> #include < ...
- 乐视(LeTV)占用8080端口
- 粗略整理的java面试题
1.垃圾回收 是回收的空闲堆空间 只有在cpu空闲并且堆空间不足的情况下才回收 2.threadlocal 就是为线程的变量都提供了一个副本,每个线程运行都只是在更新这个副本. Threadloc ...
- SQL Server 行转列,列转行。多行转成一列
一.多行转成一列(并以","隔开) 表名:A 表数据: 想要的查询结果: 查询语句: SELECT name , value = ( STUFF(( SELECT ',' + va ...
- SQL注入详解
SQL是一种将SQL代码添加到输入参数中,传递到SQL服务器解析并执行的一种攻击手段 产生的原因 web开发人员无法保证所有输入都已经安全过滤 攻击者利用发送给SQL服务器的输入数据,构造可执行的SQ ...
- Vue.js用法详解(一)更新中~
前 言 前段时间为了一个数据查询的项目自学了Vue,感觉这款框架还是很不错的,今天就整理整理这个框架如何使用,希望对正在学这个框架的小伙伴有所帮助~ 首先,我们先来了解一下Vue: Vue.js ...
- JMeter基础教程3:脚本录制篇
对于一些JMeter初学者来说,录制脚本可能是最容易掌握的技能之一.虽然我不建议录制性能脚本(因为录制的脚本比较混乱,必须要通过二次处理才可正常使用),但有时做总比不做要好,是吧?下面我们详细介绍使用 ...
- '@P0'附近有语法错误
做一个分页查询功能,使用到了TOP #{pagenum}然后就报错了.'@P0'附近有语法错误 未解决:#{pagenum}改成${pagenum},但是mybatis报参数未找到错误, 解决:将对应 ...