bfs搜索加记录路径

HDOJ-1043

  • 主要思路就是使用双向广度优先搜索,找最短路径。然后记录路径,找到结果是打印出来。
  • 使用康拓序列来来实现状态的映射。
  • 打印路径推荐使用vector最后需要使用algorithm里的reverse进行路径的翻转。
  • 注意本题有多组输入,这里的输入需要注意一下。
  • 如果题目没有要求最短路径,那么使用深搜的话也可以记录路径,这里也给出了代码。
  • 这里的记录路径的方法可以学习。还有判断没有解决方案的解决,利用逆序数。
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<queue>
#include<string>
#include<vector>
#include<map>
using namespace std;
const int maxn=362880;
int state[maxn][9];//从1开始
struct node{
int x;
int y;
int state;//编码
string s;
};
int fact[9];//阶乘
bool vis[maxn];
bool visr[maxn];
map<int,char> ma;
map<int,char> mar;
void init(){
fact[0]=1;
for(int i=1;i<=8;i++){
fact[i]=fact[i-1]*i;
}
ma[0]='u';mar[0]='d';
ma[1]='l';mar[1]='r';
ma[2]='d';mar[2]='u';
ma[3]='r';mar[3]='l';
}
int computeCon(string s){
int code=0;
for(int i=0;i<9;i++){
int cnt=0;
for(int j=i+1;j<9;j++){
if(s[j]-'0'<s[i]-'0')
cnt++;
}
code+=fact[8-i]*cnt;
}
return code;
}
int dir[4][2]={{-1,0},{0,-1},{1,0},{0,1}};
bool in(int x,int y){
return x>=0&&x<3&&y>=0&&y<3;
}
string path[maxn];//-----------------------这种记录路径的方法很好----------------------------------
void bfs(string s,string final){
memset(vis,0,sizeof(vis));
memset(visr,0,sizeof(visr));
queue<node> q;
queue<node> q1;
int sx,sy;
for(int i=0;i<9;i++){
if(state[1][i]==0){
sx=i/3;
sy=i%3;
break;
}
}
int con=computeCon(s);
vis[con]=true;
node sta=node{sx,sy,con,s};
q.push(sta);
int conr=computeCon(final);
visr[conr]=true;
q1.push(node{2,2,conr,final});
path[con]="";
path[conr]="";
while(!q.empty()){
node temp=q.front();
q.pop();
//cout<<temp.state<<endl;
// if(temp.s==final){
// //print(temp.state);
// cout<<path[temp.state]<<endl;
// return true;
// }
for(int i=0;i<4;i++){
int tx=temp.x+dir[i][0];
int ty=temp.y+dir[i][1];
int newz=tx*3+ty;
int oldz=temp.x*3+temp.y;
if(in(tx,ty)){
string ns=temp.s;
ns[newz]=temp.s[oldz];
ns[oldz]=temp.s[newz];
int nowcon=computeCon(ns);
char direction=ma[i];
if(visr[nowcon]){
reverse(path[nowcon].begin(),path[nowcon].end());
cout<<path[temp.state]<<ma[i]<<path[nowcon]<<endl;
return;
}
if(!vis[nowcon]){
vis[nowcon]=1;
node now;
now.x=tx,now.y=ty,now.s=ns,now.state=nowcon;
q.push(now);
path[nowcon]=path[temp.state];
path[nowcon]+=direction;
//path[nowcon]=now;
//cout<<now.s<<endl;
}
}
}
temp=q1.front();
q1.pop();
for(int i=0;i<4;i++){
int tx=temp.x+dir[i][0];
int ty=temp.y+dir[i][1];
int newz=tx*3+ty;
int oldz=temp.x*3+temp.y;
if(in(tx,ty)){
string ns=temp.s;
ns[newz]=temp.s[oldz];
ns[oldz]=temp.s[newz];
int nowcon=computeCon(ns);
char direction=mar[i];
if(vis[nowcon]){
reverse(path[temp.state].begin(),path[temp.state].end());
cout<<path[nowcon]<<mar[i]<<path[temp.state]<<endl;
return;
}
if(!visr[nowcon]){
visr[nowcon]=1;
node now;
now.x=tx,now.y=ty,now.s=ns,now.state=nowcon;
q1.push(now);
path[nowcon]=path[temp.state];
path[nowcon]+=direction;
//path[nowcon]=now;
//cout<<now.s<<endl;
}
}
}
}
}
int main(){
ios::sync_with_stdio(false);
cin.tie(0);
init();
char c;
while(cin>>c){
string s="";
if(c=='x')
state[1][0]=0;
else state[1][0]=c-'0';
s+=(state[1][0]+'0');
for(int i=1;i<=8;i++){
cin>>c;
if(c=='x')
state[1][i]=0;
else state[1][i]=c-'0';
s+=(state[1][i]+'0');
}
//cout<<s<<endl;
string final="123456780";
int k=0;
for(int i=0;i<9;i++){
if(!state[1][i])
continue;
for(int j=i+1;j<9;j++){
if(state[1][j]<state[1][i]&&state[1][j]){
k++;
}
}
}
if(k&1){
cout<<"unsolvable"<<endl;
continue;
}
bfs(s,final);
}
return 0;
}

这里是未Ac超时了的代码,而且记录路径的方法没有上面好。

#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<queue>
#include<string>
#include<vector>
#include<map>
using namespace std;
const int maxn=362880;
int state[maxn][9];//从1开始
struct node{
int x;
int y;
int state;//编码
int father;
char direction;
string s;
};
int fact[9];//阶乘
bool vis[maxn];
map<int,char> ma;
map<string,int> conma;
void init(){
fact[0]=1;
for(int i=1;i<=8;i++){
fact[i]=fact[i-1]*i;
}
ma[0]='u';
ma[1]='l';
ma[2]='d';
ma[3]='r';
}
int computeCon(string s){
int code=0;
for(int i=0;i<9;i++){
int cnt=0;
for(int j=i+1;j<9;j++){
if(s[j]-'0'<s[i]-'0')
cnt++;
}
code+=fact[8-i]*cnt;
}
return code;
}
int dir[4][2]={{-1,0},{0,-1},{1,0},{0,1}};
bool in(int x,int y){
return x>=0&&x<3&&y>=0&&y<3;
}
node path[maxn];
void print(int state){
vector<char> v;
//cout<<state<<endl;
while(path[state].direction!='n'){
//cout<<state<<endl;
v.push_back(path[state].direction);
state=path[state].father;
}
reverse(v.begin(),v.end());
for(int i=0;i<v.size();i++){
cout<<v[i];
}
cout<<endl;
}
bool bfs(string s,string final){
memset(vis,0,sizeof(vis));
queue<node> q;
int sx,sy;
for(int i=0;i<9;i++){
if(state[1][i]==0){
sx=i/3;
sy=i%3;
break;
}
}
int con=computeCon(s);
vis[con]=true;
node sta=node{sx,sy,con,-1,'n',s};
q.push(sta);
path[con]=sta;
while(!q.empty()){
node temp=q.front();
q.pop();
//cout<<temp.state<<endl;
if(temp.s==final){
print(temp.state);
return true;
}
for(int i=0;i<4;i++){
int tx=temp.x+dir[i][0];
int ty=temp.y+dir[i][1];
int newz=tx*3+ty;
int oldz=temp.x*3+temp.y;
if(in(tx,ty)){
string ns=temp.s;
ns[newz]=temp.s[oldz];
ns[oldz]=temp.s[newz];
int nowcon=computeCon(ns);
if(!vis[nowcon]){
vis[nowcon]=1;
node now;
char direction=ma[i];
now.x=tx,now.y=ty,now.father=temp.state,now.direction=direction,now.s=ns,now.state=nowcon;
q.push(now);
path[nowcon]=now;
//cout<<now.s<<endl;
}
}
}
}
return false;
}
int main(){
init();
char c;
while(cin>>c){
string s="";
if(c=='x')
state[1][0]=0;
else state[1][0]=c-'0';
s+=(state[1][0]+'0');
for(int i=1;i<=8;i++){
cin>>c;
if(c=='x')
state[1][i]=0;
else state[1][i]=c-'0';
s+=(state[1][i]+'0');
}
//cout<<s<<endl;
string final="123456780";
if(!bfs(s,final)){
cout<<"unsolvable"<<endl;
}
}
return 0;
}

HDOJ-1043 Eight(八数码问题+双向bfs+高效记录路径+康拓展开)的更多相关文章

  1. hdu 1043 Eight (八数码问题)【BFS】+【康拓展开】

    <题目链接> 题目大意:给出一个3×3的矩阵(包含1-8数字和一个字母x),经过一些移动格子上的数后得到连续的1-8,最后一格是x,要求最小移动步数. 解题分析:本题用BFS来寻找路径,为 ...

  2. 八数码问题 双向BFS/Hsh链表存储

    转自洛谷 作者EndSaH #include<iostream> #include<string> #include<cmath> #include<cstr ...

  3. cdoj 414 八数码 (双向bfs+康拓展开,A*)

    一道关乎人生完整的问题. DBFS的优越:避免了结点膨胀太多. 假设一个状态结点可以扩展m个子结点,为了简单起见,假设每个结点的扩展都是相互独立的. 分析:起始状态结点数为1,每加深一层,结点数An ...

  4. HDU 1043 Eight 八数码问题 A*算法(经典问题)

    HDU 1043 Eight 八数码问题(经典问题) 题意 经典问题,就不再进行解释了. 这里主要是给你一个状态,然后要你求其到达\(1,2,3,4,5,6,7,8,x\)的转移路径. 解题思路 这里 ...

  5. Hdu 1043 Eight (八数码问题)

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=1043 题目描述: 3*3的格子,填有1到8,8个数字,还有一个x,x可以上下左右移动,问最终能否移动 ...

  6. HUD 1043 Eight 八数码问题 A*算法 1667 The Rotation Game IDA*算法

    先是这周是搜索的题,网站:http://acm.hdu.edu.cn/webcontest/contest_show.php?cid=6041 主要内容是BFS,A*,IDA*,还有一道K短路的,.. ...

  7. 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 ...

  8. hdu1043 经典的八数码问题 逆向bfs打表 + 逆序数

    题意: 题意就是八数码,给了一个3 * 3 的矩阵,上面有八个数字,有一个位置是空的,每次空的位置可以和他相邻的数字换位置,给你一些起始状态 ,给了一个最终状态,让你输出怎么变换才能达到目的. 思路: ...

  9. 【算法系列学习三】[kuangbin带你飞]专题二 搜索进阶 之 A-Eight 反向bfs打表和康拓展开

    [kuangbin带你飞]专题二 搜索进阶 之 A-Eight 这是一道经典的八数码问题.首先,简单介绍一下八数码问题: 八数码问题也称为九宫问题.在3×3的棋盘,摆有八个棋子,每个棋子上标有1至8的 ...

随机推荐

  1. HDOJ1232 畅通工程 DFS

    很早之前就做过的题以前用并查集做的 现在用DFS重做算是熟悉DFS吧 #include<stdio.h>#include<string.h>const int size=100 ...

  2. zjnu1745 DOMINE (状压dp+1*2铺砖)

    Description Mirko has a chessboard with N rows and just three columns. Slavica has written an intege ...

  3. poj 1511-- Invitation Cards (dijkstra+优先队列)

    刚开始想复杂了,一直做不出来,,,其实就是两遍dijkstra+优先队列(其实就是板子题,只要能有个好的板子,剩下的都不是事),做出来感觉好简单...... 题意:有n个车站和n个志愿者,早上每个志愿 ...

  4. hdu5491 The Next

    Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission ...

  5. 2015ACM/ICPC亚洲区沈阳站-重现赛 M - Meeting (特殊建边,最短路)

    题意:有\(n\)个点,\(m\)个集合,集合\(E_i\)中的点都与集合中的其它点有一条边权为\(t_i\)的边,现在问第\(1\)个点和第\(n\)个点到某个点的路径最短,输出最短路径和目标点,如 ...

  6. .net webapi 中使用session是出错 HttpContext.Current.Session==null

    最近在写.net webapi时发现 HttpContext.Current.Session==null  ,导致报错,后来查资料发现webapi中使用session时首先需要开启session功能, ...

  7. k8s二进制部署 - coredns安装

    coredns的资源清单文件rabc.yaml apiVersion: v1 kind: ServiceAccount metadata: name: coredns namespace: kube- ...

  8. OpenStack Train版-7.neutron网络服务概述

    网络服务NEUTRON概述 一.NEUTRON架构 OpenStack的网络服务neutron是整个OpenStack中最复杂的一个部分,它的基本架构是一个中心服务(neutron-server)外加 ...

  9. 2021-2-17:Java HashMap 的中 key 的哈希值是如何计算的,为何这么计算?

    首先,我们知道 HashMap 的底层实现是开放地址法 + 链地址法的方式来实现. 即数组 + 链表的实现方式,通过计算哈希值,找到数组对应的位置,如果已存在元素,就加到这个位置的链表上.在 Java ...

  10. DB-Engines Ranking : Redis, MongoDB, MySQL

    DB-Engines Ranking http://db-engines.com/en/ranking The DB-Engines Ranking ranks database management ...