首页 > 代码库 > HDU 1195 Open the Lock 双向BFS

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