BFS之四(双向bfs和康托压缩)

/*

双向BFS就是从起点 和 终点 同时开始搜索。由起点搜索(BSF1)得到的点标记为1,
由终点搜索(BFS2)得到的点标记为2。当某一时刻BFS1搜索到了已经标记为2的点(或BFS2搜到
了1号点),说明发生相遇,那么答案就是由bfs1和bfs2分别求得的两段路径长度的和。

简单的分析:设每次的BFS,总的搜索状态数是r^L(r是搜索的分支数,L是搜索层数)。而采
取双向BFS算法,那么,从前往后、从后往前,分别需要搜索L/2层,合起来就是2*(r^(L/2))
这要比一般的BFS快的多。

可以看到,双向BFS不过就是在while循环中套了两个节点扩展模块,一个是qu1,一个是qu2
二者轮流执行、轮流扩展。qu1扩展一次,然后qu2扩展一次,直到二者中有点相遇为止。

*/

//poj 1077 Eight
#include <iostream>            //双向bfs和康托压缩
#include <deque>
#include
<string>
#include
<cmath>
using namespace std;
int visited[1000000];
int fac[]={1,1,2,6,24,120,720,5040,40320,362880}; //9!表
string path1[1000000],path2[1000000];
int cantor(int arr[])
{
int temp,num=1;
for(int i=0;i<9;++i)
{
temp
=0;
for(int j=i+1;j<9;++j)
if(arr[j]<arr[i])
temp
++;
num
+=fac[8-i]*temp;
}
return num;
}
void to_arr(int list[],int num)
{
int i;
for(i=0;i<9;++i)
list[i]
=0;
i
=8;
while(num)
{
list[i
--]=num%9;
num
/=9;
}
}
int to_num(int list[])
{
int n=0;
for(int i=0;i<9;++i)
n
=n*9+list[i];
return n;
}

int move[4]={-3,3,1,-1};
char pos[4]={'u','d','r','l'};
struct node //空间开销是58276K
{
string state;
int num;
int sub;
node(
string str,int n,int dir,int s)
{
int arr[9];
to_arr(arr,n);
num
=n;
state
=str;
if(dir==0)
sub
=s;
else
{
state.push_back(pos[dir
-1]);
swap(arr[s
+move[dir-1]],arr[s]);
num
=to_num(arr);
sub
=s+move[dir-1];
}
}
};
deque
<node> forword,backword;
int main()
{
int arr[9]={1,2,3,4,5,6,7,8,0},loc;
node bck(
"",to_num(arr),0,8);
backword.push_back(bck);
char ch;
for(int i=0;i<9;++i)
{
cin
>>ch;
if(ch=='x')
arr[i]
=0,loc=i;
else
arr[i]
=int(ch-48);
}
node forw(
"",to_num(arr),0,loc);
forword.push_back(forw);
while(!forword.empty())
{
node temp
=forword.front();
forword.pop_front();

to_arr(arr,temp.num);
int d=cantor(arr);
if(visited[d]==2)
{
cout
<<temp.state;
for(int k=path2[d].size()-1;k>=0;--k)
{
ch
=path2[d][k];
if(ch=='u')
cout
<<'d';
else if(ch=='d')
cout
<<'u';
else if(ch=='r')
cout
<<'l';
else
cout
<<'r';
}
cout
<<endl;

return 0;
}
else if(visited[d]==0)
{
visited[d]
=1;
path1[d]
=temp.state;
if(temp.sub>=3)
{
node puzzle(temp.state,temp.num,
1,temp.sub);
forword.push_back(puzzle);
}
if(temp.sub<6)
{
node puzzle(temp.state,temp.num,
2,temp.sub);
forword.push_back(puzzle);
}
if(temp.sub%3!=2)
{
node puzzle(temp.state,temp.num,
3,temp.sub);
forword.push_back(puzzle);
}
if(temp.sub%3!=0)
{
node puzzle(temp.state,temp.num,
4,temp.sub);
forword.push_back(puzzle);
}
}

if(!backword.empty())
{
node temp
=backword.front();
backword.pop_front();
to_arr(arr,temp.num);
int d=cantor(arr);
if(visited[d]==1)
{
cout
<<path1[d];
for(int k=temp.state.size()-1;k>=0;--k)
{
ch
=temp.state[k];
if(ch=='u')
cout
<<'d';
else if(ch=='d')
cout
<<'u';
else if(ch=='r')
cout
<<'l';
else
cout
<<'r';
}
cout
<<endl;
return 0;
}
else if(visited[d]==0)
{
visited[d]
=2;
path2[d]
=temp.state;
if(temp.sub>=3) //u d r l
{
node puzzle(temp.state,temp.num,
1,temp.sub);
backword.push_back(puzzle);
}
if(temp.sub<6)
{
node puzzle(temp.state,temp.num,
2,temp.sub);
backword.push_back(puzzle);
}
if(temp.sub%3!=2)
{
node puzzle(temp.state,temp.num,
3,temp.sub);
backword.push_back(puzzle);
}
if(temp.sub%3!=0)
{
node puzzle(temp.state,temp.num,
4,temp.sub);
backword.push_back(puzzle);
}
}
}
}
cout
<<"unsolvable\n";
return 0;
}

  

转载于:https://www.cnblogs.com/mjc467621163/archive/2011/08/22/2149141.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值