ACM-BFS之Open the Lock——hdu1195(双向BFS)

这道题的0基础版本号,暴力BFS及题目详情请戳:http://blog.csdn.net/lttree/article/details/24658031


上回书说道,要用双向BFS来尝试一下。

最终AC了,

双向BFS,就是从两个点寻找一个共同的中间点。

然后把各自到这个中间点的步数加起来,及为最短步数。

肯定有人问了。双向BFS有啥优点捏?

鄙人,有图有真相!

单BFS:


双向BFS:


发现了不?

尤其是随着搜索广度的增大。那个范围是相当di啊!


双向BFS做法事实上不难,两个队列。

一个从头開始搜。一个从尾開始搜。

可是要注意一点,要逐层搜索。不要逐点搜索呀~

要在 正向的同一层搜索完后,再去搜索反向的对应层!

什么叫逐层搜索呢?

对于这道题而言,VIS数组须要记录到达该点的步数,

对于每层搜索要把,同一步数的点全出队列遍历一遍,再进行反向搜索。

OK。这是对于这道题的双向广搜代码(感觉就是把两个广搜叠起来就OK了)


/**************************************
***************************************
*        Author:Tree                 *
*From  :http://blog.csdn.net/lttree  *
* Title : Scrambled Polygon           *
*Source: hdu 1195                     *
* Hint  : 双向BFS                     *
***************************************
**************************************/

#include <iostream>
#include <string.h>
#include <queue>
using namespace std;
struct VIS
{
    int flag,step;
}vis[10001];
struct Key
{
    int k[4],step;
    friend bool operator <(Key a,Key b)
    {
        return a.step<b.step;
    }
};
int ini[4],ans[4],dis[2]={-1,1};
int solu[9]={9,1,2,3,4,5,6,7,8};
bool judge(Key a)
{
    for(int i=0;i<4;++i)
        if( a.k[i]!=ans[i] )
            return false;
    return true;
}
// 用来做VIS数组
int total(Key a)
{
    int i,sum;
    sum=0;
    for(i=0;i<4;++i)
        sum=sum*10+a.k[i];
    return sum;
}
int bfs(void)
{
    memset(vis,0,sizeof(vis));
    queue <Key> q;
    queue <Key> p;
    Key pre,lst;
    int i,t,sum,sp=0;

    // 初始化。。。

for(i=0;i<4;++i) pre.k[i]=ini[i]; sum=total(pre); vis[sum].flag=1; vis[sum].step=0; pre.step=0; q.push(pre); for(i=0;i<4;++i) lst.k[i]=ans[i]; sum=total(lst); vis[sum].flag=2; vis[sum].step=0; lst.step=0; p.push(lst); while( !q.empty() && !p.empty() ) { // 为了遍历每一层的情况,所以用sp来控制层数 // 正向搜索 while( q.front().step==sp ) { pre=q.front(); q.pop(); for(i=0; i<4; ++i) { if( pre.k[i]!=ans[i] ) { for(t=0; t<2; ++t) { lst=pre; lst.k[i]=solu[(pre.k[i]+dis[t])%9]; sum=total(lst); lst.step=pre.step+1; if( vis[sum].flag==1 ) continue; if( vis[sum].flag==2 ) return lst.step+vis[sum].step; vis[sum].flag=1; vis[sum].step=lst.step; q.push(lst); } } } for(i=0; i<3; ++i) { lst=pre; lst.k[i]=pre.k[i+1]; lst.k[i+1]=pre.k[i]; sum=total(lst); lst.step=pre.step+1; if( vis[sum].flag==1 ) continue; if( vis[sum].flag==2 ) return lst.step+vis[sum].step; vis[sum].flag=1; vis[sum].step=lst.step; q.push(lst); } } // 反向搜索 while( p.front().step==sp ) { pre=p.front(); p.pop(); for(i=0; i<4; ++i) { if( pre.k[i]!=ini[i] ) { for(t=0; t<2; ++t) { lst=pre; lst.k[i]=solu[(pre.k[i]+dis[t])%9]; sum=total(lst); lst.step=pre.step+1; if( vis[sum].flag==2 ) continue; if( vis[sum].flag==1 ) return lst.step+vis[sum].step; vis[sum].flag=2; vis[sum].step=lst.step; p.push(lst); } } } for(i=0; i<3; ++i) { lst=pre; lst.k[i]=pre.k[i+1]; lst.k[i+1]=pre.k[i]; sum=total(lst); lst.step=pre.step+1; if( vis[sum].flag==2 ) continue; if( vis[sum].flag==1 ) return lst.step+vis[sum].step; vis[sum].flag=2; vis[sum].step=lst.step; p.push(lst); } } ++sp; } } int main() { int i,s,test; char c; cin>>test; while( test-- ) { // 输入数据 for(i=0;i<4;++i) { cin>>c; ini[i]=c-'0'; } for(i=0;i<4;++i) { cin>>c; ans[i]=c-'0'; } s=bfs(); cout<<s<<endl; } return 0; }




原文地址:https://www.cnblogs.com/tlnshuju/p/7144281.html