`
lovnet
  • 浏览: 6880642 次
  • 性别: Icon_minigender_1
  • 来自: 武汉
文章分类
社区版块
存档分类
最新评论

HDOJ 1195 Open the Lock (双向BFS)

 
阅读更多

http://acm.hdu.edu.cn/showproblem.php?pid=1195

题意:要从一个4位数,变成另一个4位数。有3种变换方法:1、选择一位加1(9+1变成1);2、选择一位减1(1-1变成9);3、选择相邻的两位交换其数值(第一位与第四位不相邻)。求最少的步数。

思路:这是我第一次写出双向BFS~可怜用两个队列分别记录正向的bfs和反向的back_bfs,用map进行查重,map中的第二个值记录当前关键字的步数。搜一层正向的,并判断有没有在反向中出现;再搜一层反向的,并判断有没有在正向中出现。循环上面的搜索过程,直到搜到正向和反向中有交集(即搜到相同关键字)位置,将正向和反向的步数加和即可。

注意:一定要一层一层搜!!!!

第一次写双向BFS,代码可能写得不好,仅供参考

#include<iostream>
#include<algorithm>
#include<string>
#include<queue>
#include<map>

using namespace std;

struct node
{
    string password;
    int cnt;
}now,tmp;

string beg,end;
map<string,int>back_vis;
map<string,int>vis;
queue<struct node>q;
queue<struct node>back_q;

int back_bfs(int n)//反向BFS,每次只搜一层,即第n层
{
    while(back_q.front().cnt<=n)
    {
        now=back_q.front();
        back_q.pop();
        for(int i=0;i<4;i++)
        {
            //各个位-1
            tmp=now;
            if(tmp.password[i]!='1')
                tmp.password[i]--;
            else
                tmp.password[i]='9';
            if(vis.find(tmp.password)!=vis.end())//判断是否在正向队列中找到
                return tmp.cnt+1+vis[tmp.password];
            if(back_vis.find(tmp.password)==back_vis.end())
            {
                tmp.cnt++;
                back_q.push(tmp);
                back_vis[tmp.password]=tmp.cnt;
            }
            //各个位+1
            tmp=now;
            if(tmp.password[i]!='9')
                tmp.password[i]++;
            else
                tmp.password[i]='1';
            if(vis.find(tmp.password)!=vis.end())//判断是否在正向队列中找到
                return tmp.cnt+1+vis[tmp.password];
            if(back_vis.find(tmp.password)==back_vis.end())
            {
                tmp.cnt++;
                back_q.push(tmp);
                back_vis[tmp.password]=tmp.cnt;
            }
        }
        for(int i=0;i<3;i++)
        {
            tmp=now;
            swap(tmp.password[i],tmp.password[i+1]);
            if(vis.find(tmp.password)!=vis.end())//判断是否在正向队列中找到
                return tmp.cnt+1+vis[tmp.password];
            if(back_vis.find(tmp.password)==back_vis.end())
            {
                tmp.cnt++;
                back_q.push(tmp);
                back_vis[tmp.password]=tmp.cnt;
            }
        }
    }
    return -1;
}

int bfs()
{
    while(!q.empty())
        q.pop();//清空正向BFS的队列
    now.password=beg;
    now.cnt=0;
    q.push(now);
    vis[beg]=0;
    while(!q.empty())
    {
        int n=q.front().cnt;
        while(q.front().cnt<=n)
        {
            now=q.front();
            q.pop();
            for(int i=0;i<4;i++)
            {
                //各个位-1
                tmp=now;
                if(tmp.password[i]!='1')
                    tmp.password[i]--;
                else
                    tmp.password[i]='9';
                if(back_vis.find(tmp.password)!=back_vis.end())//判断是否在反向队列中找到
                    return tmp.cnt+1+back_vis[tmp.password];
                if(vis.find(tmp.password)==vis.end())
                {
                    tmp.cnt++;
                    q.push(tmp);
                    vis[tmp.password]=tmp.cnt;
                }
                //各个位+1
                tmp=now;
                if(tmp.password[i]!='9')
                    tmp.password[i]++;
                else
                    tmp.password[i]='1';
                if(back_vis.find(tmp.password)!=back_vis.end())//判断是否在反向队列中找到
                    return tmp.cnt+1+back_vis[tmp.password];
                if(vis.find(tmp.password)==vis.end())
                {
                    tmp.cnt++;
                    q.push(tmp);
                    vis[tmp.password]=tmp.cnt;
                }
            }
            for(int i=0;i<3;i++)
            {
                tmp=now;
                swap(tmp.password[i],tmp.password[i+1]);
                if(back_vis.find(tmp.password)!=back_vis.end())//判断是否在反向队列中找到
                    return tmp.cnt+1+back_vis[tmp.password];
                if(vis.find(tmp.password)==vis.end())
                {
                    tmp.cnt++;
                    q.push(tmp);
                    vis[tmp.password]=tmp.cnt;
                }
            }
        }
        int ret=back_bfs(now.cnt);
        if(ret!=-1)
            return ret;
    }
}

int main()
{
    int t;
    while(cin>>t)
    {
        while(t--)
        {
            cin>>beg;
            cin>>end;
            vis.clear();//清空map
            back_vis.clear();//清空map
            while(!back_q.empty())
                back_q.pop();//清空反向BFS的队列
            now.password=end;
            now.cnt=0;
            back_q.push(now);
            back_vis[end]=0;//将反向BFS的起始点入队列标记
            int ret=bfs();
            cout<<ret<<endl;
        }
    }
    return 0;
}


分享到:
评论

相关推荐

    HDOJ题目分类 HDOJ题目分类

    【标题】:“HDOJ题目分类 HDOJ题目分类” HDOJ,全称为Happy DingO Online Judge,是一个在线编程竞赛平台,它为参赛者提供了大量编程题目进行练习和比赛,旨在提升编程技能和算法理解。HDOJ的题目分类是帮助用户...

    hdoj.rar_Dividing HDOJ_OJ 1082_hdoj 10_杭电oj_杭电oj1000

    【标题】"hdoj.rar_Dividing HDOJ_OJ 1082_hdoj 10_杭电oj_杭电oj1000" 涉及的知识点主要围绕着“杭电在线判题系统(HDOJ)”以及其中的题目1082和10系列题目。HDOJ是杭州电子科技大学主办的一个在线编程竞赛平台,...

    HDOJ_1010 Tempter of the Bone

    总之,解决【HDOJ_1010 诱惑者的骨头】的关键在于理解图的概念,掌握图的遍历算法(DFS或BFS),并正确处理时间限制。通过编程实现这些算法,我们可以有效地判断是否存在一条满足条件的路径,从而解决这个问题。在...

    HDOJ1002

    ACM ICPC HDOJ1002

    HDOJ1001

    ACM ICPC HDOJ1001

    hdoj1001标程

    hdoj1001标程

    HDOJ部分简单题(JAVA)

    HDOJ1000.java HDOJ1001.java HDOJ1089.java HDOJ1090.java HDOJ1091.java HDOJ1092.java HDOJ1093.java HDOJ1094.java HDOJ1095.java HDOJ1108.java HDOJ1406.java HDOJ2001.java HDOJ2002.java HDOJ2003.java HDOJ...

    hdoj1004 解题代码 答案

    hdoj1004,解题代码,答案代码,欢迎下载

    HDOJ 80题 Java

    【标题】"HDOJ 80题 Java"是一份专为Java程序员设计的在线编程挑战集合,源自杭州电子科技大学(HDOJ)的在线评测系统。这些题目旨在帮助Java开发者提升算法理解与编程能力,同时也为那些习惯于C++但希望在Java环境...

    HDOJ1003

    ACM ICPC HDOJ1003

    HDOJ 1008

    ACM ICPC HDOJ1008

    HDOJ离线版

    《HDOJ离线版:探索编程竞赛的智慧宝库》 HDOJ,全称为“杭州电子科技大学在线评测系统”(Hangzhou Dianzi University Online Judge),是中国早期的编程竞赛平台之一,深受广大编程爱好者和在校学生的喜爱。HDOJ...

    hdoj--acm题目,有注释

    "hdoj--acm题目,有注释" 本资源提供了多个 ACM 题目的解决方案,代码都带有注释,非常适合初学者学习。下面是对每个题目的知识点总结: 2000:本题目要求输入三个字符,输出按照从小到大排序的结果。本代码使用了...

    ACM HDOJ 课件

    【ACM HDOJ 课件】是一套涵盖了多种计算机科学竞赛中常见算法与理论的教育资源,主要针对ACM(国际大学生程序设计竞赛)和HDOJ(华中地区大学生在线编程题库)的训练。这些课件深入浅出地讲解了在解决复杂问题时所需...

    HDOJ1000

    ACM ICPC HDOJ1000

    hdoj2066最短路

    根据给定的文件信息,我们可以总结出以下关于“hdoj2066最短路径”的相关知识点: ## hdoj2066最短路径概述 ### 标题解析:“hdoj2066最短路” - **hdoj**:High Density Online Judge(高密度在线评测系统),是...

    HDOJ DP题目总结

    一些HDOJ上的DP题目的小总结,但愿能帮到那些想专攻DP的人吧

    OJ.tar.gz_HDOJ _OJ源码_oj

    【OJ.tar.gz_HDOJ _OJ源码_oj】是一个包含编程竞赛平台HDOJ(Happy Ding Octopus Judge)部分源代码的压缩文件。这个压缩包的主要目的是供学习和研究使用,尤其是针对50至60题目的解题算法和系统实现。通过分析这些...

    hdoj1002——大整数相加

    ### hdoj1002——大整数相加 #### 题目背景与目的 本题目来源于杭州电子科技大学的在线评测系统(HDOJ),编号为1002的大整数相加问题。该题目主要考察的是编程者对于大整数处理的基本技巧以及对数组、循环等基础...

    HDOJ.rar_HD_HDOJ

    【标题】"HDOJ.rar_HD_HDOJ" 是一个与HDU(杭州电子科技大学)在线判题系统HDOJ相关的压缩包文件,其中包含了大量编程题目的源代码。 【描述】提到,这个压缩包包含了几百道HDOJ题目的源代码,这意味着它是一个宝贵...

Global site tag (gtag.js) - Google Analytics