HDU1195 双向BFS(或BFS)

  题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1195 , 双向BFS或者直接BFS也可以过。

  其实这道题只是单向BFS就可以过的,但是为了练算法,所以还是用了双向BFS来写。



算法:

  先预处理一下,从1111到9999的所有点进行构图(由于是1~9的,所以除去含有0元素的数字),能进行一次变换变成的数字则表示两点之间连通。然后从初态与目态两个点进行BFS,如果有轨迹重合的就返回路程和。

  这里注意双向BFS要一层一层的进行搜索,不然的话会产生错误,至于错误原因还在思考中。。

双向BFS代码:

#include <iostream>
#include <cstdio>
#include <vector>
#include <queue>
#include <cmath>
#include <string>
#include <string.h>
#include <algorithm>
using namespace std;
#define LL __int64
#define eps 1e-8
#define INF 1e8
#define lson l , m , rt << 1
#define rson m + 1 , r , rt << 1 | 1
const int MOD = 2333333;
const int maxn = 10000 + 5;
vector <int> e[maxn];
int vis[maxn] , dist[maxn];

void solve(int x)
{
    int num[4] , i , tmp , y;
    i = 0;
    tmp = x;
    while(tmp) {
        num[i++] = tmp % 10;
        tmp /= 10;
    }
    for(i = 0 ; i < 4 ; i++)
        if(num[i] == 0)
            return;
    for(i = 0 ; i < 4 ; i++) {
        if(i < 3) {
            swap(num[i] , num[i + 1]);
            y = num[3] * 1000 + num[2] * 100 + num[1] * 10 + num[0];
            e[x].push_back(y);
            e[y].push_back(x);
            swap(num[i] , num[i + 1]);
        }
        tmp = num[i];
        if(num[i] == 9)
            num[i] = 1;
        else
            num[i]++;
        y = num[3] * 1000 + num[2] * 100 + num[1] * 10 + num[0];
        e[x].push_back(y);
        e[y].push_back(x);
        num[i] = tmp;

        if(num[i] == 1)
            num[i] = 9;
        else
            num[i]--;
        y = num[3] * 1000 + num[2] * 100 + num[1] * 10 + num[0];
        e[x].push_back(y);
        e[y].push_back(x);
        num[i] = tmp;
    }
}
int BFS_2(int start , int end)
{
    if(start == end)
        return 0;
    memset(vis , 0 , sizeof(vis));
    queue <int> que[2];
    vis[start] = 1;
    vis[end] = 2;
    que[0].push(start);
    que[1].push(end);
    dist[start] = dist[end] = 0;
    while(!que[0].empty() && !que[1].empty()) {
        int k = 0;
        if(que[0].size() < que[1].size())
            k++;
        int u = que[k].front();
        que[k].pop();
        for(int i = 0 ; i < e[u].size() ; i++) {
            int j = e[u][i];
            if(!vis[j]) {
                vis[j] = vis[u];
                que[k].push(j);
                dist[j] = dist[u] + 1;
            } else if(vis[j] == vis[u]) {
                continue;
            } else {
                return dist[j] + dist[u] + 1;
            }
        }
    }
    return -1;
}
int main()
{
    int T , a , b;
    for(int i = 1111 ; i <= 9999 ; i++)
        solve(i);
    cin >> T;
    while(T--) {
        scanf("%d %d" , &a , &b);
        printf("%d\n" , BFS_2(a , b));
    }
    return 0;
}

BFS代码:

#include <iostream>
#include <cstdio>
#include <vector>
#include <queue>
#include <cmath>
#include <string>
#include <string.h>
#include <algorithm>
using namespace std;
#define LL __int64
#define eps 1e-8
#define INF 1e8
#define lson l , m , rt << 1
#define rson m + 1 , r , rt << 1 | 1
const int MOD = 2333333;
const int maxn = 10000 + 5;
vector <int> e[maxn];
int vis[maxn] , dist[maxn];

void solve(int x)
{
    int num[4] , i , tmp , y;
    i = 0;
    tmp = x;
    while(tmp) {
        num[i++] = tmp % 10;
        tmp /= 10;
    }
    for(i = 0 ; i < 4 ; i++)
        if(num[i] == 0)
            return;
    for(i = 0 ; i < 4 ; i++) {
        if(i < 3) {
            swap(num[i] , num[i + 1]);
            y = num[3] * 1000 + num[2] * 100 + num[1] * 10 + num[0];
            e[x].push_back(y);
            e[y].push_back(x);
            swap(num[i] , num[i + 1]);
        }
        tmp = num[i];
        if(num[i] == 9)
            num[i] = 1;
        else
            num[i]++;
        y = num[3] * 1000 + num[2] * 100 + num[1] * 10 + num[0];
        e[x].push_back(y);
        e[y].push_back(x);
        num[i] = tmp;

        if(num[i] == 1)
            num[i] = 9;
        else
            num[i]--;
        y = num[3] * 1000 + num[2] * 100 + num[1] * 10 + num[0];
        e[x].push_back(y);
        e[y].push_back(x);
        num[i] = tmp;
    }
}
int BFS(int a , int b)
{
    if(a == b)
        return 0;
    memset(vis , 0 , sizeof(vis));
    queue <int> que;
    que.push(a);
    vis[a] = 1;
    dist[a] = 0;
    while(!que.empty()) {
        int u = que.front();
        que.pop();
        for(int i = 0 ; i < e[u].size() ; i++) {
            int j = e[u][i];
            if(j == b)
                return dist[u] + 1;
            if(!vis[j]) {
                dist[j] = dist[u] + 1;
                vis[j] = 1;
                que.push(j);
            }
        }
    }
}
int main()
{
    int T , a , b;
    for(int i = 1111 ; i <= 9999 ; i++)
        solve(i);
    cin >> T;
    while(T--) {
        scanf("%d %d" , &a , &b);
        printf("%d\n" , BFS(a , b));
    }
    return 0;
}
时间: 2024-07-30 10:20:04

HDU1195 双向BFS(或BFS)的相关文章

POJ 2251 Dungeon Master --- 三维BFS(用BFS求最短路)

POJ 2251 题目大意: 给出一三维空间的地牢,要求求出由字符'S'到字符'E'的最短路径,移动方向可以是上,下,左,右,前,后,六个方向,每移动一次就耗费一分钟,要求输出最快的走出时间.不同L层的地图,相同RC坐标处是相连通的.(.可走,#为墙) 解题思路:从起点开始分别往6个方向进行BFS(即入队),并记录步数,直至队为空.若一直找不到,则困住. /* POJ 2251 Dungeon Master --- 三维BFS(用BFS求最短路) */ #include <cstdio> #i

POJ1475 Pushing Boxes(BFS套BFS)

描述 Imagine you are standing inside a two-dimensional maze composed of square cells which may or may not be filled with rock. You can move north, south, east or west one cell at a step. These moves are called walks. One of the empty cells contains a b

FZU 2196 Escape(BFS预处理+BFS搜索)

Problem 2196 Escape Accept: 123    Submit: 678 Time Limit: 1000 mSec    Memory Limit : 32768 KB Problem Description 小明进入地下迷宫寻找宝藏,找到宝藏后却发生地震,迷宫各处产生岩浆,小明急忙向出口处逃跑.如果丢下宝藏,小明就能迅速离开迷宫,但小明并不想轻易放弃自己的辛苦所得.所以他急忙联系当程序员的朋友你(当然是用手机联系),并告诉你他所面临的情况,希望你能告诉他是否能成功带着宝藏

Graph 133. Clone Graph in three ways(bfs, dfs, bfs(recursive))

Clone an undirected graph. Each node in the graph contains a label and a list of its neighbors. OJ's undirected graph serialization: Nodes are labeled uniquely. We use # as a separator for each node, and , as a separator for node label and each neigh

UVa1599 Ideal Path(双向bfs+字典序+非简单图的最短路+队列判重)

题目大意: 对于一个n个房间m条路径的迷宫(Labyrinth)(2<=n<=100000, 1<=m<=200000),每条路径上都涂有颜色,颜色取值范围为1<=c<=10^9.求从节点1到节点n的一条路径,使得经过的边尽量少,在这样的前提下,如果有多条路径边数均为最小,则颜色的字典序最小的路径获胜.一条路径可能连接两个相同的房间,一对房间之间可能有多条路径.输入保证可以从节点1到达节点n. 更多细节可以参考原题:UVa1599 分析: 从题目中我们可以看出,题目中的

UVA 1599 Ideal Path(双向bfs+字典序+非简单图的最短路+队列判重)

https://vjudge.net/problem/UVA-1599 给一个n个点m条边(2<=n<=100000,1<=m<=200000)的无向图,每条边上都涂有一种颜色.求从结点1到结点n的一条路径,使得经过的边数尽量少,在此前提下,经过边的颜色序列的字典序最小.一对结点可能有多条边,一条边可能连接相同的结点(自环).输入保证结点1可以到达结点n.颜色是1~10^9的整数. 分析: 从题目中我们可以看出,题目中的无向图是可以出现自环和重边的,自环我们可以在输入的时候检查并排

hdu 1242 Rescue(bfs+优先队列)

Angel was caught by the MOLIGPY! He was put in prison by Moligpy. The prison is described as a N * M (N, M <= 200) matrix. There are WALLs, ROADs, and GUARDs in the prison. Angel's friends want to save Angel. Their task is: approach Angel. We assume

HDU ACM 1044 Collect More Jewels BFS+DFS

题意:在一个迷宫中,有一些宝物,从起点走到终点,问在给定的时间内,到达终点后所能拾取珠宝的最大价值. 分析(BFS+DFS): 1.求入口到第一个取宝物的地方的最短距离 2.求第i个取宝物的地方到第i+1个取宝物的地方的最短距离 3.求第n个取宝物的地方到出口的最短距离 4.保证以上3点能在时间L内实现的情况下,取得的宝石价值最大. BFS特点:对于解决最短或最少问题特别有效,而且寻找深度小,但缺点是内存耗费量大(需要开大量的数组单元来存储状态) DFS特点:对于解决遍历和求所有问题有效,对于问

BFS [SWUST OJ 191] 迷宫逃离

迷宫逃离(0191) 描述 江鸟突然想到了一个迷宫逃离的游戏,话说有三个人被困于一个n*m的迷宫里,他们三人都可以向上.向下.向左.向右四个方向进行走动,当然他们所在的初始位置没有障碍物,同时只能走到没有障碍物的格子上,现在江鸟要问你最少需要去掉多少个格子的障碍物,可以使他们三人之间两两互相可达. 输入 输入包括多组测试数据,每组测试数据第一行为两个整数n和m(2<=n,m<=100),接下来n行,每行m个字符,其中:‘w’.‘W’.‘f’分别代表那三个人:‘.’代表没有障碍物的格子,‘#’代