Eight HDU - 1043 (双向BFS)
记得上人工智能课的时候老师讲过一个A*算法,计算估价函数(f[n]=h[n]+g[n])什么的,感觉不是很好理解,百度上好多都是用逆向BFS写的,我理解的逆向BFS应该是从终点状态出发,然后把每一种状态打表列举出来,最后O(1)查询就可以了。这种办法确实挺好,但是不会....。
这位大佬用的双向BFS https://blog.csdn.net/qq_41670466/article/details/84110090,挺好理解的,但是注释什么的比较少,也没有过多的介绍思路,所以我想借助这篇blog简单的介绍一下这个题目的双向BFS的思路。
双向BFS就是终点状态(从后向前)和起始状态(从前向后)一起寻找,当且仅当而且碰头时,就是答案了。
针对本题来说,初始状态就是输入的转态,终点状态都是一样的123456780(x用0来代替),但是这个状态怎么表示呢?康托展开 (不会的可以点开看一下)。状态表示解决完了,接下来我们看一下转态转移。
当x处在0 3 6这三个位置时,不可以向左移动,当x处于2 5 8这三个位置时,不可以向右移动,当x处于0 1 2这三个位置时,不可以向上移动,处于6 7 8这三个位置时,不可以向下移动。 对于本题样例,s[]=2 3 4 1 5 x 7 6 8。,x是处于5这个位置,如果向上移动,就可以看成s[5]和s[5-3]交换了一下,向下移动可以看成s[5]和s[5+3]交换了一下,
向左s[5]和s[5-1]向右同理....这样就实现了状态之间的转移。
路径的记录。维护两个数组char 和int ,char 用来记录向哪移动了,int 用来记录上一个状态的下标。
最后还要加一个特判,问题是否有解跟逆序对有关,如果逆序对是奇数就有解,否则就无解具体为什么跟线性代数有关吧~~我也不太懂(待解释)。
具体实现都在code中了....
- #include<bits/stdc++.h>
- using namespace std;
- const int maxn=5e5+;
- string a;
- int ha[]={,,,,,,,,};//从8到0对应的阶乘
- int vis[maxn],vis2[maxn];
- struct node {
- int num;
- char ch;
- }pre[maxn];//write path
- struct stu {
- string s;//当前串
- int num;//x的位置
- }e;//save now state
- int direction[]={-,,-,};//udlr
- string s1="udlr",s2="durl";
- int ct(string s){//当前串对应的康托值
- int sum=;
- for(int i=;i<;i++){
- int k=;
- for(int j=i+;j<;j++){
- if(s[j]<s[i]) k++;
- }
- sum+=k*ha[i];
- }
- return sum;
- }
- void writhpath(int x){
- if(pre[x].num==-) return ;
- writhpath(pre[x].num);
- printf("%c",pre[x].ch);
- }
- void bfs(){
- queue<stu> que1,que2;
- int q=ct(e.s);
- vis[q]=;
- stu f,g;
- f.s="";
- f.num=;
- int p=ct(f.s);
- vis2[p]=;
- pre[].num=-;pre[].num=-;
- int num=;
- que1.push(e);que2.push(f);
- while(que1.size()&&que2.size()){
- f=que1.front();que1.pop();
- p=ct(f.s);
- if(vis2[p]){
- writhpath(vis[p]);
- int k=vis2[p];
- while(pre[k].num!=-) {
- printf("%c",pre[k].ch);
- k=pre[k].num;
- }
- cout<<endl;
- return ;
- }
- else{
- for(int i=;i<;i++){
- if(i==&&f.num<) continue ;
- if(i==&&f.num>) continue ;
- if(i==&&f.num%==) continue ;
- if(i==&&f.num%==) continue ;
- int dx=f.num+direction[i];g=f;
- swap(g.s[f.num],g.s[dx]);
- q=ct(g.s);
- if(vis[q]) continue ;
- vis[q]=++num;g.num=dx;
- que1.push(g);
- pre[num].num=vis[p];pre[num].ch=s1[i];
- }
- }
- f=que2.front();que2.pop();
- p=ct(f.s);
- if(vis[p]){
- writhpath(vis[p]);
- int k=vis2[p];
- while(pre[k].num!=-) {
- printf("%c",pre[k].ch);
- k=pre[k].num;
- }
- cout<<endl;
- return ;
- }
- else{
- for(int i=;i<;i++){
- if(i==&&f.num<) continue ;
- if(i==&&f.num>) continue ;
- if(i==&&f.num%==) continue ;
- if(i==&&f.num%==) continue ;
- int dx=f.num+direction[i];g=f;
- swap(g.s[f.num],g.s[dx]);
- q=ct(g.s);
- if(vis2[q]) continue ;
- vis2[q]=++num;g.num=dx;
- que2.push(g);
- pre[num].num=vis2[p];pre[num].ch=s2[i];
- }
- }
- }
- puts("unsolvable");
- }
- int main(){
- while(getline(cin,a)){
- string c="";
- int n=a.size(),pos=,j=;
- for(int i=;i<n;i++){
- if(a[i]==' ') continue ;
- if(a[i]=='x'){
- c+='';pos=j;
- }
- else {
- c+=a[i];j++;
- }
- }
- int k=;e.num=pos;e.s=c;
- for (int i=;i<;i++){
- if (e.s[i]=='')continue;
- for (int j = ;j<i;j++){
- if (e.s[j] == '')continue;
- if (e.s[j]>e.s[i])k++;
- }
- }
- if(k&) {
- puts("unsolvable");
- }
- else {
- memset(vis,,sizeof vis);
- memset(vis2,,sizeof vis2);
- bfs();
- }
- }
- return ;
- }
Eight HDU - 1043 (双向BFS)的更多相关文章
- HDU - 3085 双向BFS + 技巧处理 [kuangbin带你飞]专题二
题意:有两只鬼,一个男孩女孩被困在迷宫中,男孩每秒可以走三步,女孩只能1步,鬼可以两步且可以通过墙.问男孩女孩是否可以在鬼抓住他们之前会合? 注意:每秒开始鬼先移动,然后两人开始移动. 思路:以男孩和 ...
- hdu 3085(双向bfs)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3085 思路:双向广搜,每次从M出发,搜三步,从G出发,搜一步,然后就是判断是否走到对方已经走过的格子, ...
- HDU 1043 Eight BFS
题意:就是恢复成1,2,3,4,5,6,7,8,0; 分析:暴力BFS预处理,所有路径,用康拓展开判重,O(1)打印 93ms 还是很快的 #include <iostream> #inc ...
- HDU 1043 Eight (BFS·八数码·康托展开)
题意 输出八数码问题从给定状态到12345678x的路径 用康托展开将排列相应为整数 即这个排列在全部排列中的字典序 然后就是基础的BFS了 #include <bits/stdc++.h ...
- HDU 1043 Eight(双向BFS+康托展开)
http://acm.hdu.edu.cn/showproblem.php?pid=1043 题意:给出一个八数码,求出到达指定状态的路径. 思路:路径寻找问题.在这道题里用到的知识点挺多的.第一次用 ...
- Eight (HDU - 1043|POJ - 1077)(A* | 双向bfs+康拓展开)
The 15-puzzle has been around for over 100 years; even if you don't know it by that name, you've see ...
- hdu 1043 Eight(双向bfs)
题意:经典八数码问题 思路:双向bfs ps:还有a*算法(还不会)等解法. 代码: #include<iostream> #include<stdio.h> #include ...
- HDU 3085 Nightmare II 双向bfs 难度:2
http://acm.hdu.edu.cn/showproblem.php?pid=3085 出的很好的双向bfs,卡时间,普通的bfs会超时 题意方面: 1. 可停留 2. ghost无视墙壁 3. ...
- 2017多校第10场 HDU 6171 Admiral 双向BFS或者A*搜索
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6171 题意: 给你一个高度为6的塔形数组,你每次只能将0与他上下相邻的某个数交换,问最少交换多少次可以 ...
随机推荐
- Error: clean-webpack-plugin only accepts an options object. See: https://github.com/johnagan/clean-webpack-plugin#options-and-defaults-optional
webpack中文文档中推荐这样使用,but 执行npm run build Error: clean-webpack-plugin only accepts an options object. S ...
- Worktile正式入驻飞书,助力企业轻松实现敏捷开发与协作
企业在敏捷研发中时常面临着交付延期.需求不匹配等问题,如何更高效地完成敏捷研发? Worktile携手飞书,为企业用户提供敏捷开发服务,帮助企业实现软件项目的需求管理.缺陷追踪.迭代规划与推进以及效能 ...
- Python中的数值类型总结
本文参考书:<Learning Python>中文版--<Python 学习手册>第四版 Python中包含大量的数值类型,他们中的大部分与其他编程语言保持一致,因此学习他们就 ...
- sqoop面试题
1.1 Sqoop 在工作中的定位是会用就行1.1.1 Sqoop导入数据到hdfs中的参数 /opt/module/sqoop/bin/sqoop import \ --connect \ # 特殊 ...
- 微信APP支付-java后台实现
不说废话,直接上代码 先是工具类(注意签名时要排序): import java.io.BufferedReader; import java.io.ByteArrayInputStream; impo ...
- 分享一个超级好用的SM图床
分享一个超级好用的SM图床 大家都知道我是一个喜欢sm Markdown的人,但是Markdown有个很不方便的地方,就是图片的插入,一般用Markdown编辑器(我用的是Typora)直接插入图 ...
- 【Pytest01】全网最全最新的Pytest框架快速入门
一.Pytest简介pytest是一个非常成熟的全功能的Python测试框架,主要有一下几个特点:1.简单灵活,容易上手,支持参数化2.能够支持简单的单元测试和复杂的功能测试,还可以用来做seleni ...
- python中如何在一个for循环中遍历两个列表
`其实就是用zip把两个列表包装起来: for x, y in zip(list1, list2)
- Java中for(;;)和while(true)的区别
while(true): public class Test { public static void main(String[] args) { while(true) { } } } 在?看看汇编 ...
- ASP.NET Core单文件和多文件上传并保存到服务端
前言: 在我们日常开发中,关于图片,视频,音频,文档等相关文件上传并保存到服务端中是非常常见的一个功能,今天主要是把自己在开发中常用的两种方式记录下来方便一下直接使用,并且希望能够帮助到有需要的同学! ...