万能的搜索--之BFS(三)

接着(一)start

(二)广度优先搜索(BFS)

广度优先搜索(又称宽度优先搜索算法)是最简便的图的搜索算法之一,这一算法也是很多重要的图的算法的原型。   Dijkstra单源最短路径算法和Prim最小生成树算法都采用了和宽度优先搜索类似的思想。其别名又叫BFS,属于一种盲目搜寻法,目的是系统地展开并检查图中的所有节点,以找寻结果。换句话说,它并不考虑结果的可能位置,彻底地搜索整张图,直到找到结果为止。

广搜的核心思想就是:从初始结点开始,产生第一层节点,检查目标结点是否在这些后继结点之中,没有,就扩展第一层节点,若没有,用产生式规则得到第二层节点;检查目标结点是否在这些后继结点之中,没有,就扩展第 二层节点……像这样以此扩展节点、检查,直到发现目标结点为止。

优点:
找到的第一个解一定是最优解
缺点:
占用空间比较大

经典题:八数码问题、

在3×3的棋盘,摆有八个棋子,每个棋子上标有1至8的某一数字,不同棋子上标的数字不相同。棋盘上还有一个空格,与空格相邻的棋子可以移到空格中。
给出一个初始状态和一个目标状态,找出一种从初始转变成目标状态的移动棋子步数最少的移动步骤。

伪代码:

初始状态加入队列
while 队列非空
获取当前队首状态
for 当前状态可能的下一状态st
if 该状态之前未被搜索到
if 该状态为目标状态
输出并退出
else
加入队尾

如何判重:

如何判断某一状态之前是否出现过?
将状态转换为一个数字(Hash)
举例
abac(字符串)转化为数字
0 * 26^3 + 1 * 26^2 + 0 * 26 + 2
矩阵转化为数字

具体代码实现:

#include<stdio.h>

struct node
{
    int xy[3][3];
    int dir;
};
struct node sh[102], end;
int count = 1;

void init()
{
    printf("输入起始节点的位置:\n");
    int i, j;
    for (i = 0; i < 3; i++)
        for (j = 0; j < 3; j++)
            scanf("%d", &sh[0].xy[i][j]);
    sh[0].dir = -1;
    printf("输入目标节点的位置:\n");
    for (i = 0; i < 3; i++)
        for (j = 0; j < 3; j++)
            scanf("%d", &sh[101].xy[i][j]);
    sh[101].dir = -1;
}

//找出0的位置
int loction(int num)
{
    int i;
    for (i = 0; i < 9; i++)
        if (sh[num].xy[i / 3][i % 3] == 0) return i;
}

//进行标记
long long sign(int num)
{
    long long  sum;
    sum = sh[num].xy[0][0]*100000000 + sh[num].xy[0][1]*10000000 + sh[num].xy[0][2]*1000000 + sh[num].xy[1][0]*100000 + sh[num].xy[1][1]*10000 + sh[num].xy[1][2]*1000 + sh[num].xy[2][0]*100 + sh[num].xy[2][1]*10 + sh[num].xy[2][2];
    return sum;
}

void mobile(int num)
{

    int temp;
    int loc;
    int up = 1, down = 1, left = 1, right = 1;
    loc = loction(num);
    int stand = sh[num].dir;
    //dir的0 1 2 3分别代表左 上 右 下
    if (loc / 3 != 0 && stand != 1)
    {
        sh[count] = sh[num];
        temp = sh[count].xy[loc / 3][loc % 3];
        sh[count].xy[loc / 3][loc % 3] = sh[count].xy[loc / 3 - 1][loc % 3];
        sh[count].xy[loc / 3 - 1][loc % 3] = temp;
        sh[count].dir = 3;
        count++;
    };
    if (loc / 3 != 2 && stand != 3)
    {
        sh[count] = sh[num];
        temp = sh[count].xy[loc / 3][loc % 3];
        sh[count].xy[loc / 3][loc % 3] = sh[count].xy[loc / 3 + 1][loc % 3];
        sh[count].xy[loc / 3 + 1][loc % 3] = temp;
        sh[count].dir = 1;
        count++;
    }
    if (loc % 3 != 0 && stand != 0)
    {
        sh[count] = sh[num];
        temp = sh[count].xy[loc / 3][loc % 3];
        sh[count].xy[loc / 3][loc % 3] = sh[count].xy[loc / 3][loc % 3 - 1];
        sh[count].xy[loc / 3][loc % 3 - 1] = temp;
        sh[count].dir = 2;
        count++;
    }
    if (loc % 3 != 2 && stand != 2)
    {
        sh[count] = sh[num];
        temp = sh[count].xy[loc / 3][loc % 3];
        sh[count].xy[loc / 3][loc % 3] = sh[count].xy[loc / 3][loc % 3 + 1];
        sh[count].xy[loc / 3][loc % 3 + 1] = temp;
        sh[count].dir = 0;
        count++;
    }

}
void display(int num)
{
    int i, j;
    for (i = 0; i < 3; i++)
    {
        for (j = 0; j < 3; j++)
            printf("%d ", sh[num].xy[i][j]);
        printf("\n");
    }
}

int search()
{
    int i = 0;
    while (1)
    {
        printf("\n");
        display(i);
        printf("\n");
        if (i == 100)
        {
            printf("超出了上限次数\n");
            return 0;
        }
        if (sign(i) == sign(101))
        {
            printf("在第%d次找到了", i);
            display(i);
            return i;
        }
        mobile(i);
        i++;
    }
}

int main()
{
    init();
    search();
    return 0;
}

未完.....

此为个人略解,转载请标明出处:http://www.cnblogs.com/rmy020718/p/8836137.html

原文地址:https://www.cnblogs.com/rmy020718/p/8836137.html

时间: 2025-01-09 04:39:47

万能的搜索--之BFS(三)的相关文章

层层递进——宽度优先搜索(BFS)

问题引入 我们接着上次“解救小哈”的问题继续探索,不过这次是用宽度优先搜索(BFS). 注:问题来源可以点击这里 http://www.cnblogs.com/OctoptusLian/p/7429645.html 最开始小哼在入口(1,1)处,一步之内可以到达的点有(1,2)和(2,1). 但是小哈并不在这两个点上,那小哼只能通过(1,2)和(2,1)这两点继续往下走. 比如现在小哼走到了(1,2)这个点,之后他又能够到达哪些新的点呢?有(2,2).再看看通过(2,1)又可以到达哪些点呢?可以

迷宫问题(maze problem)——深度优先(DFS)与广度优先搜索(BFS)求解

1.问题简介 给定一个迷宫,指明起点和终点,找出从起点出发到终点的有效可行路径,就是迷宫问题(maze problem). 迷宫可以以二维数组来存储表示.0表示通路,1表示障碍.注意这里规定移动可以从上.下.左.右四方方向移动.坐标以行和列表示,均从0开始,给定起点(0,0)和终点(4,4),迷宫表示如下: int maze[5][5]={ {0,0,0,0,0}, {0,1,0,1,0}, {0,1,1,0,0}, {0,1,1,0,1}, {0,0,0,0,0} }; 那么下面的迷宫就有两条

Leetcode之广度优先搜索(BFS)专题-994. 腐烂的橘子(Rotting Oranges)

BFS入门详解:Leetcode之广度优先搜索(BFS)专题-429. N叉树的层序遍历(N-ary Tree Level Order Traversal) 在给定的网格中,每个单元格可以有以下三个值之一: 值 0 代表空单元格: 值 1 代表新鲜橘子: 值 2 代表腐烂的橘子. 每分钟,任何与腐烂的橘子(在 4 个正方向上)相邻的新鲜橘子都会腐烂. 返回直到单元格中没有新鲜橘子为止所必须经过的最小分钟数.如果不可能,返回 -1. 示例 1: 输入:[[2,1,1],[1,1,0],[0,1,1

Dearboy&#39;s Puzzle (poj 2308 搜索 dfs+bfs)

Language: Default Dearboy's Puzzle Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 1202   Accepted: 208 Description Dearboy is a game lover. Recently, he loves playing the game Lian Lian Kan. This game is played on a board with N*M grids

第四章、万能的搜索

第一节.深度优先搜索p78 输出全排列的 dfs 方法 #include <stdio.h> int a[10],book[10],n; void dfs(int step) { int i; if(step==n+1) { for(i=1;i<=n;i++) printf("%d",a[i]); printf("\n"); return; } for(i=1;i<=n;i++) { if(book[i]==0) { a[step]=i; b

[C++]广度优先搜索(BFS)(附例题)

广度优先搜索(BFS)(附例题) 问题产生: Isenbaev是国外的一个大牛. 现在有许多人要参加ACM ICPC. 一共有n个组,每组3个人.同组的3个人都是队友. 大家都想知道自己与大牛的最小距离是多少. 大牛与自己的最小距离当然是0.大牛的队友和大牛的最小距离是1.大牛的队友的队友和大牛的最小距离是2--以此类推. 如果实在和大牛没有关系的只好输出undefined了. 第一行读入n.表示有n个组.1 ≤ n ≤ 100 接下来n行,每行有3个名字,名字之间用空格隔开.每个名字的开头都是

队列的JS实现及广度优先搜索(BFS)的实现

队列是先进先出(FIFO)的数据结构,插入操作叫做入队,只能添加在队列的末尾:删除操作叫做出队,只能移除第一个元素.在JS中,用数组可以很简单的实现队列. function Queue () { this.queue = []; } // 增加 Queue.prototype.enQueue = function(x) { this.queue.push(x); return true; } // 删除 Queue.prototype.deQueue = function() { if(this

深度优先搜索(DFS)与广度优先搜索(BFS)的Java实现

1.基础部分 在图中实现最基本的操作之一就是搜索从一个指定顶点可以到达哪些顶点,比如从武汉出发的高铁可以到达哪些城市,一些城市可以直达,一些城市不能直达.现在有一份全国高铁模拟图,要从某个城市(顶点)开始,沿着铁轨(边)移动到其他城市(顶点),有两种方法可以用来搜索图:深度优先搜索(DFS)和广度优先搜索(BFS).它们最终都会到达所有连通的顶点,深度优先搜索通过栈来实现,而广度优先搜索通过队列来实现,不同的实现机制导致不同的搜索方式. 1.1 深度优先搜索 深度优先搜索算法有如下规则: 规则1

Z1. 广度优先搜索(BFS)解题思路

/** BFS 解题思路 特点:从某些特定的节点开始,感染相邻的节点; 被感染的节点,再感染其相邻的节点,以此类推. 题目常见于数据结构包括 二维数组.树.图 **/ /** 1). 二维数组特定节点感染相邻的节点,即上下左右四个方向,可设定变化数组如下 int[] dr = new int[]{-1, 0, 1, 0}; int[] dc = new int[]{0, -1, 0, 1}; 2). 二维数组特定节点感染包围它的节点,即八个方法, 可设定变化数组如下: int[] dr = ne