HDU 1195 Open the Lock 双向BFS

题目链接:Open the Lock

题意:就是给定两个4位数,起始,结束。问从起始数字到达结束数字 最少变换多少步,每个数 可以+1 / -1 或交换位置,都算做是一步。

单广,双广都用了,感觉双向BFS,太棒了,HDU的这个题双向BFS时间优化的太棒了

有图,有真相!

时间优化了近9倍。。。

PS:今天还学习一个sscanf函数,挺棒的

单搜的代码就不贴了,贴个双搜的

#include<cstdio>
#include <iostream>
#include<cstring>
#include <queue>
const int N = 10001; //因为是1-9 4位数  所以10000肯定够
using namespace std;
int vis[N];
int dis[N];
struct node
{
    char a[5];
};
char st[5],en[5];
void BFS()
{
    queue<node>q;
    node f,t;
    strcpy(f.a,st);
    q.push(f);
    int w,mm;
    sscanf(f.a,"%d",&w);
    memset(vis,0,sizeof(vis));
    memset(dis,0,sizeof(dis));
    dis[w] = 0;
    vis[w] = 1; // 从起点开始搜素的路线标记为1
    strcpy(f.a,en);

    q.push(f);
    sscanf(f.a,"%d",&w);
    dis[w] = 0;
    vis[w] = 2;  //从终点开始搜素的路线标记为2

    while(!q.empty())
    {
        t = q.front();
        q.pop();

        for(int i = 0;i<3;i++)
        {
            if(i==0)
            {
                sscanf(t.a,"%d",&mm);
                for(int j = 0;j<=3;j++)
             {
                f = t;
                if(f.a[j]=='9')  f.a[j] = '1';
                else   f.a[j] += 1;
                sscanf(f.a,"%d",&w);
                if(!vis[w])
                {
                    vis[w] = vis[mm];
                    dis[w] = dis[mm] + 1;
                    q.push(f);
                }
                else if(vis[w]!=vis[mm])
                {
                    printf("%d\n",dis[w]+dis[mm]+1);
                    return ;
                }
             }
            }
           else if(i==1)
           {
               sscanf(t.a,"%d",&mm);
                for(int j = 0;j<=3;j++)
             {
                f = t;
                if(f.a[j]=='1')  f.a[j] = '9';
                else   f.a[j] -= 1;
                sscanf(f.a,"%d",&w);
                if(!vis[w])
                {
                    vis[w] = vis[mm];
                    dis[w] = dis[mm] + 1;
                    q.push(f);
                }
                else if(vis[w]!=vis[mm])
                {
                    printf("%d\n",dis[w]+dis[mm]+1);
                    return ;
                }
             }
           }
           else if(i==2)
            {
                sscanf(t.a,"%d",&mm);
                for(int j = 0;j<3;j++)
                {
                    f = t;
                    char g = f.a[j];
                    f.a[j] = f.a[j+1];
                    f.a[j+1] = g;
                    sscanf(f.a,"%d",&w);
                    if(!vis[w])
                    {
                        vis[w] = vis[mm];
                        dis[w] = dis[mm] + 1;
                        q.push(f);
                    }
                else if(vis[w]!=vis[mm])
                {
                    printf("%d\n",dis[w]+dis[mm]); //  +1 /-1 两者相遇时都没变换状态,所以要加1步,而两数交换就是一步,所以不用加+
                    return ;
                }
            }
            }
        }
    }
}
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%s%s",st,en);
        if(strcmp(st,en)==0)
            printf("0\n");
        else
        BFS();
    }
    return 0;
}

测试数据,乱写的,以下都对了,应该就能AC

10

1234

6541

9

1111

1111

0

9999

9999

0

1111

1118

2

9911

1199

3

9512

3258

7

1238

9845

7

1111

2222

4

1111

6666

16

9559

9555

4

6554

4556

4

HDU 1195 Open the Lock 双向BFS

时间: 2024-10-08 00:10:43

HDU 1195 Open the Lock 双向BFS的相关文章

hdu 1195 Open the Lock (bfs+优先队列)

Open the Lock Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 4253    Accepted Submission(s): 1858 Problem Description Now an emergent task for you is to open a password lock. The password is c

HDU 1195 Open the Lock (双向广搜)

题意:给你初始4个数字和目标4个数字,问是否能由初始经过变换到目标数字: 变换规则:每个数字可以加1(9+1=1)或减1(1-1=9),或交换相邻的数字(最左和最右不是相邻的). 双向广搜:分别对初始和目标数字进行广搜,vis数组用1和2标记两种已搜索的数字,用mp数组记录状态的步数. 当从前往后搜可以到达2或从后往前搜可以到达1状态则就可以了... #include<stdio.h> #include<string.h> #include<string> #inclu

hdu 1195:Open the Lock(暴力BFS广搜)

mediaxyz是一位研究ffmpeg有三年的高人了,这几天一直在折腾ffmpeg中的x264,就是不知道该如何控制码率,主要是参数太多,也不知道该如何设置,在 google上search了一下,这方面的介绍为0,那就找mediaxyz请教请教吧,这些可都是经验,非常宝贵! 以下是与mediaxyz在QQ上聊天的记录,只有一部分,因为QQ把之前的谈话删除了,但基本上精髓都可这里了. mediaxyz 23:40:26你说的qsable是c->global_quality吧 Leon 23:40:

HDU 1195 Open the Lock (不一样的BFS)

Open the Lock Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 6045    Accepted Submission(s): 2697 Problem Description Now an emergent task for you is to open a password lock. The password is c

hdu - 1195 Open the Lock (bfs)

http://acm.hdu.edu.cn/showproblem.php?pid=1195 这道题虽然只是从四个数到四个数,但是状态很多,开始一直不知道怎么下手,关键就是如何划分这些状态,确保每一个状态都能遍历到. 得到四个数之后,分三种情况处理,每次改变一个数之后都要加入队列,最先输出的就是步数最少. 1 #include <cstdio> 2 #include <cstring> 3 #include <queue> 4 using namespace std;

HDU 1195.Open the Lock

Open the Lock Time Limit:1000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64u SubmitStatusPracticeHDU 1195 Description Now an emergent task for you is to open a password lock. The password is consisted of four digits. Each digit is numbe

HDU 1195 Open the Lock (双宽搜索)

意甲冠军:给你一个初始4数字和目标4数字,当被问及最初的目标转换为数字后,. 变换规则:每一个数字能够加1(9+1=1)或减1(1-1=9),或交换相邻的数字(最左和最右不是相邻的). 双向广搜:分别对初始和目标数字进行广搜,vis数组用1和2标记两种已搜索的数字,用mp数组记录状态的步数. 当从前往后搜能够到达2或从后往前搜能够到达1状态则就能够了... #include<stdio.h> #include<string.h> #include<string> #in

HDU 1043 Eight(双向BFS+康托展开)

http://acm.hdu.edu.cn/showproblem.php?pid=1043 题意:给出一个八数码,求出到达指定状态的路径. 思路:路径寻找问题.在这道题里用到的知识点挺多的.第一次用双向BFS来做. ①双向BFS 在单向BFS的基础上,多建一个从终止状态开始搜索的队列,当然这个时候需要两个vis[]辅助数组,分别记录两个队列的访问情况,当两个队列相遇时即可终止循环. ②康托展开 X=a[n]*(n-1)!+a[n-1]*(n-2)!+...+a[i]*(i-1)!+...+a[

HDU 1242 -Rescue (双向BFS)&amp;&amp;( BFS+优先队列)

题目链接:Rescue 进度落下的太多了,哎╮(╯▽╰)╭,渣渣我总是埋怨进度比别人慢...为什么不试着改变一下捏.... 开始以为是水题,想敲一下练手的,后来发现并不是一个简单的搜索题,BFS做肯定出事...后来发现题目里面也有坑 题意是从r到a的最短距离,"."相当时间单位1,"x"相当时间单位2,求最短时间 HDU 搜索课件上说,这题和HDU1010相似,刚开始并没有觉得像剪枝,就改用  双向BFS   0ms  一Y,爽! 网上查了一下,神牛们竟然用BFS+