hdu 1195 Open the Lock(BFS && DBFS)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1195


推荐一个个人感觉讲解得比较好的DBFS的博客

http://blog.sina.com.cn/s/blog_8627bf080100ticx.html


        所谓双向广搜,就是初始结点向目标结点和目标结点向初始结点同时扩展,直至在两个扩展方向上出现同一个结点,搜索结束。它适用的问题是,扩展结点较多,而目标结点又处在深沉,如果采用单纯的广搜解题,搜索量巨大,搜索速度慢是可想而知的,同时往往也会出现内存空间不够用的情况,这时双向广搜的作用就体现出来了。双向广搜对单纯的广搜进行了改良或改造,加入了一定的“智能因数”,使搜索能尽快接近目标结点,减少了在空间和时间上的复杂度。


思路:

这道题不是很难,主要是用来练习一下搜索。


用基础的BFS就可以过,时间46ms,不明白为什么discuss里会有超时的现象。

每次搜索遍历11个方向,每个数位加减一或者交换相邻数位。


用DBFS,时间0ms,用两个队列,从起始两个方向开始搜索,开标记数组,若第一个队列访问过标记为1,第二个队列访问过标记为2。

若都放访问过,说明在两个扩展方向上出现同一个节点,搜索结束。


BFS:

#include <limits.h>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <algorithm>
#include <iostream>
#include <iterator>
#include <sstream>
#include <queue>
#include <stack>
#include <string>
#include <vector>
#include <set>
//#define ONLINE_JUDGE
#define eps 1e-6
#define INF 0x7fffffff                                          //INT_MAX
#define inf 0x3f3f3f3f                                          //int??????????????????
#define FOR(i,a) for((i)=0;i<(a);(i)++)                          //[i,a);
#define MEM(a) (memset((a),0,sizeof(a)))
#define sfs(a) scanf("%s",a)
#define sf(a) scanf("%d",&a)
#define sfI(a) scanf("%I64d",&a)
#define pf(a) printf("%d\n",a)
#define pfI(a) printf("%I64d\n",a)
#define pfs(a) printf("%s\n",a)
#define sfd(a,b) scanf("%d%d",&a,&b)
#define sft(a,b,c)scanf("%d%d%d",&a,&b,&c)
#define for1(i,a,b) for(int i=(a);i<b;i++)
#define for2(i,a,b) for(int i=(a);i<=b;i++)
#define for3(i,a,b)for(int i=(b);i>=a;i--)
#define MEM1(a) memset(a,0,sizeof(a))
#define MEM2(a) memset(a,-1,sizeof(a))
#define MEM3(a) memset(a,0x3f,sizeof(a))
#define MEMS(a) memset(a,'\0',sizeof(a))
#define LL __int64
const double PI = acos(-1.0);
template<class T> T gcd(T a, T b) { return b ? gcd(b, a % b) : a; }
template<class T> T lcm(T a, T b) { return a / gcd(a, b) * b; }
template<class T> inline T Min(T a, T b) { return a < b ? a : b; }
template<class T> inline T Max(T a, T b) { return a > b ? a : b; }
using namespace std;
template<class T>
T Mint(T a, T b, T c) {
    if (a>b) {
        if (c>b)
            return b;
        return c;
    }
    if (c>a)
        return a;
    return c;
}
template<class T>
T Maxt(T a, T b, T c) {
    if (a>b) {
        if (c>a)
            return c;
        return a;
    }
    else if (c > b)
        return c;
    return b;
}

const int maxn=10005;
int T,n,m,k;
int init[4],ans[4],dis[2]={-1,1};
int f[9]={9,1,2,3,4,5,6,7,8};//数表
bool vis[maxn];//标记数组

struct node{
    int a[4];
    int step;
};

int fun(node p){//计算该数大小
    int ans=0;
    for1(i,0,4)
        ans=ans*10+p.a[i];
    return ans;
}

int bfs(){
    MEM1(vis);
    queue<node>q;
    node s,e,t;
    for1(i,0,4)
        s.a[i]=init[i];
    s.step=0;
    int sum=fun(s);
    vis[sum]=1;
    q.push(s);
    while(!q.empty()){
        s=q.front();
        q.pop();
        if(fun(s)==k) return s.step;
        for1(i,0,4){// // 每位数 加1或减1(若相应位置与答案不同)
            if(s.a[i]!=ans[i]){
                for1(j,0,2){
                    t=s;
                    t.a[i]=f[(s.a[i]+dis[j])%9];
                    sum=fun(t);
                    if(vis[sum])  continue;
                    t.step=s.step+1;
                    vis[sum]=1;
                    q.push(t);
                }
            }
        }
        for1(i,0,3){//交换相邻位
            t=s;
            swap(t.a[i],t.a[i+1]);
            sum=fun(t);
            if(vis[sum])  continue;
            t.step=t.step+1;
            vis[sum]=1;
            q.push(t);
        }
    }
    return -1;
}

int main(){
#ifndef ONLINE_JUDGE
    freopen("test.in","r",stdin);
    freopen("test.out","w",stdout);
#endif
    sf(T);
    while(T--){
        k=0;
        char c;
        for1(i,0,4){
            cin>>c;
            init[i]=c-'0';
        }
        for1(i,0,4){
            cin>>c;
            ans[i]=c-'0';
            k=k*10+ans[i];
        }
        int res=bfs();
        pf(res);
    }
    return 0;
}


DBFS:

#include <limits.h>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <algorithm>
#include <iostream>
#include <iterator>
#include <sstream>
#include <queue>
#include <stack>
#include <string>
#include <vector>
#include <set>
//#define ONLINE_JUDGE
#define eps 1e-6
#define INF 0x7fffffff                                          //INT_MAX
#define inf 0x3f3f3f3f                                          //int??????????????????
#define FOR(i,a) for((i)=0;i<(a);(i)++)                          //[i,a);
#define MEM(a) (memset((a),0,sizeof(a)))
#define sfs(a) scanf("%s",a)
#define sf(a) scanf("%d",&a)
#define sfI(a) scanf("%I64d",&a)
#define pf(a) printf("%d\n",a)
#define pfI(a) printf("%I64d\n",a)
#define pfs(a) printf("%s\n",a)
#define sfd(a,b) scanf("%d%d",&a,&b)
#define sft(a,b,c)scanf("%d%d%d",&a,&b,&c)
#define for1(i,a,b) for(int i=(a);i<b;i++)
#define for2(i,a,b) for(int i=(a);i<=b;i++)
#define for3(i,a,b)for(int i=(b);i>=a;i--)
#define MEM1(a) memset(a,0,sizeof(a))
#define MEM2(a) memset(a,-1,sizeof(a))
#define MEM3(a) memset(a,0x3f,sizeof(a))
#define MEMS(a) memset(a,'\0',sizeof(a))
#define LL __int64
const double PI = acos(-1.0);
template<class T> T gcd(T a, T b) { return b ? gcd(b, a % b) : a; }
template<class T> T lcm(T a, T b) { return a / gcd(a, b) * b; }
template<class T> inline T Min(T a, T b) { return a < b ? a : b; }
template<class T> inline T Max(T a, T b) { return a > b ? a : b; }
using namespace std;
template<class T>
T Mint(T a, T b, T c) {
    if (a>b) {
        if (c>b)
            return b;
        return c;
    }
    if (c>a)
        return a;
    return c;
}
template<class T>
T Maxt(T a, T b, T c) {
    if (a>b) {
        if (c>a)
            return c;
        return a;
    }
    else if (c > b)
        return c;
    return b;
}

const int maxn=10010;
int T,n,m,k;
int init[4],ans[4],dis[2]={-1,1};
int f[9]={9,1,2,3,4,5,6,7,8};//数表
int d[maxn],vis[maxn];//标记数组
bool found;

struct node{
    int a[4];
};

node s,e,t;
int sums,sume,sumt;

int fun(node p){//计算该数大小
    int ans=0;
    for1(i,0,4)
        ans=ans*10+p.a[i];
    return ans;
}

int bfs(queue<node> &q,bool flag){
    s=q.front();
    sums=fun(s);
    q.pop();
    if(flag){
        for1(i,0,4){// // 每位数 加1或减1(若相应位置与答案不同)
            if(s.a[i]!=ans[i]){
                for1(j,0,2){
                    t=s;
                    t.a[i]=f[(s.a[i]+dis[j])%9];
                    sumt=fun(t);
                    if(vis[sumt]!=1){
                        if(vis[sumt]==2){
                            found=true;
                            return d[sumt]+d[sums]+1;
                        }
                        d[sumt]=d[sums]+1;
                        vis[sumt]=1;
                        q.push(t);
                    }
                }
            }
        }
        for1(i,0,3){//交换相邻位
            t=s;
            swap(t.a[i],t.a[i+1]);
            sumt=fun(t);
            if(vis[sumt]!=1){
                if(vis[sumt]==2){
                    found=true;
                    return d[sumt]+d[sums]+1;
                }
                d[sumt]=d[sums]+1;
                vis[sumt]=1;
                q.push(t);
            }
        }
    }
    else {
        for1(i,0,4){// // 每位数 加1或减1(若相应位置与答案不同)
            if(s.a[i]!=init[i]){
                for1(j,0,2){
                    t=s;
                    t.a[i]=f[(s.a[i]+dis[j])%9];
                    sumt=fun(t);
                    if(vis[sumt]!=2){
                        if(vis[sumt]==1){
                            found=true;
                            return d[sumt]+d[sums]+1;
                        }
                        d[sumt]=d[sums]+1;
                        vis[sumt]=2;
                        q.push(t);
                    }
                }
            }
        }
        for1(i,0,3){//交换相邻位
            t=s;
            swap(t.a[i],t.a[i+1]);
            sumt=fun(t);
            if(vis[sumt]!=2){
                if(vis[sumt]==1){
                    found=true;
                    return d[sumt]+d[sums]+1;
                }
                d[sumt]=d[sums]+1;
                vis[sumt]=2;
                q.push(t);
            }
        }
    }
    return -1;
}

int DBFS(){
    found=false;
    MEM1(vis);
    MEM1(d);
    int res;
    queue<node>q1;
    queue<node>q2;
    for1(i,0,4) s.a[i]=init[i];
    for1(i,0,4) e.a[i]=ans[i];
    sums=fun(s),sume=fun(e);
    vis[sums]=1;vis[sume]=2;
    q1.push(s);q2.push(e);
    while(!q1.empty()||!q2.empty()){
        if(!q1.empty()) res=bfs(q1,true);
        if(found) return res;
        if(!q2.empty()) res=bfs(q2,false);
        if(found) return res;
    }
    return -1;
}

int main(){
#ifndef ONLINE_JUDGE
    freopen("test.in","r",stdin);
    freopen("test.out","w",stdout);
#endif
    sf(T);
    while(T--){
        char c;
        for1(i,0,4){
            cin>>c;
            init[i]=c-'0';
        }
        for1(i,0,4){
            cin>>c;
            ans[i]=c-'0';
        }
        int res=DBFS();
        pf(res);
    }
    return 0;
}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值