BFS(路径寻找问题)

很多问题都可以归结为图的遍历,但这些问题中的图却不是事先给定、从程序中读入的,而是由程序动态生成的,称为隐式图。

回溯法一般是要找一个(或者所有)满足约束的解(或者某种意义下的最优解)。

路径搜索问题可以归结为隐式图的遍历,它的任务是找到一条从初始状态到终止状态的(最优)路径。

BFS是图的广度遍历,借助队列来实现。(其实觉得图真的蛮重要,递归可以视作解答树的深度遍历这里又出现了广度遍历。)

经典问题一:迷宫问题

n*n的格子,0为路,1为墙,找出可以通关的最短路径长度

计算每一个点到起点的最短距离。如果需要路径的话就要记录它的前一个结点。

class Point{
    int x;
    int y;
    int d;
    public Point(int x, int y, int d) {
        this.x = x;
        this.y = y;
        this.d = d;
    }
}
public static void main(String[] args) {
        Scanner scn=new Scanner(System.in);
        Point[] points=new Point[4];
        points[0]=new Point(1,0,0);
        points[1]=new Point(0,1,0);
        points[2]=new Point(-1,0,0);
        points[3]=new Point(0,-1,0);

        int n=scn.nextInt();
        int[][] a=new int[n][n];
        int[][]dist=new int[n][n];
        for(int i=0;i<n;i++) {
            for(int j=0;j<n;j++) {
                a[i][j]=scn.nextInt();
                dist[i][j]=-1;
            }
        }
        Queue<Point> list=new LinkedList<Point>();
        list.add(new Point(0,0,0));
        while(!list.isEmpty()) {
            Point p=list.poll();
            for(int i=0;i<4;i++) {
                int newX=p.x+points[i].x;
                int newY=p.y+points[i].y;
                if(newX>=0&&newX<n&&newY>=0&&newY<n) {//合法
                    if(a[newX][newY]==0) {
                        if(dist[newX][newY]==-1) {
                            dist[newX][newY]=p.d+1;list.add(new Point(newX,newY,p.d+1));
                        }else if(dist[newX][newY]>p.d+1) {
                            dist[newX][newY]=p.d+1;
                            list.add(new Point(newX,newY,p.d+1));
                        }
                    }
                }
            }
        }
        System.out.println(dist[0][n-1]);
    }

经典问题二:八数码问题

3*3的格子,有一个空,从初始目标移动到最终目标,求最短移动步数

class State{
    int[] b=new int[9];
    int dist=0;
    public State getEquals() {
        int[]temp=new int[9];
        for(int i=0;i<9;i++) {
            temp[i]=b[i];
        }
        return new State(temp);
    }
    public State(int[] b) {
        super();
        this.b = b;
    }
    public boolean isEquals(State s) {
        for(int i=0;i<9;i++) {
            if(b[i]!=s.b[i])
                return false;
        }
        return true;
    }
    public int find0() {
        for(int i=0;i<9;i++) {
            if(b[i]==0)
                return i;
        }
        return -1;
    }
}
public static void main(String[] args) {
        int[] end= {8,1,5,7,3,6,4,2,0};
        State goal= new State(end);
        Queue<State> list=new LinkedList<State>();
        int[] dx= {1,-1,0,0};
        int[] dy= {0,0,1,-1};
        int[] start={8,1,5,7,3,6,4,0,2};
        list.add(new State(start));
        while(!list.isEmpty()) {
            State s=list.poll();
            if(s.equals(goal)) {
                System.out.println(s.dist);
                return;
            }
            int z=s.find0();
            int x=z/3,y=z%3;
            for(int i=0;i<4;i++) {
                int newX=x+dx[i];
                int newY=y+dy[i];
                int newZ=3*newX+newY;
                if(newX>=0&&newX<3&&newY>=0&&newY<3) {
                    //换位置
                    State st=s.getEquals();
                    st.b[z]=st.b[newZ];
                    st.b[newZ]=0;
                    st.dist=s.dist+1;
                    list.add(st);
                }
            }
        }
        System.out.println("-1");
        return;
    }

按书上给的翻译的java代码,目前这个思路我觉得是有点问题的因为在队列的这个移动会无限膨胀而不知道有没有解,可能最优解在队列里但是永远轮不到它。所以这里的队列应该是一个去重队列,出现过的不能重复出现。(BFS的判重操作)

判重:是为了避免同一个节点被重复访问多次。在树中,不需要判重因为不可能同一个节点访问两次。但是在图中,这就是非常必要的了,不然不仅会引起极大的时间和空间上的浪费,还可能无限膨胀。

原文地址:https://www.cnblogs.com/code-fun/p/12514699.html

时间: 2024-08-30 05:27:58

BFS(路径寻找问题)的相关文章

八数码问题+路径寻找问题+bfs(隐式图的判重操作)

Δ路径寻找问题可以归结为隐式图的遍历,它的任务是找到一条凑够初始状态到终止问题的最优路径, 而不是像回溯法那样找到一个符合某些要求的解. 八数码问题就是路径查找问题背景下的经典训练题目. 程序框架 process()  初始化vis数组,初始化初始节点到目标节点的移动距离 dfs()搜索到每一个节点,如果不是目标节点,对其依次扩展所有子节点,并判重,全部子节点搜索完全后,改变父节点:如果是目标节点成功返回 输出最少移动步数 input: 2 6 4 1 3 7 0 5 8 8 1 5 7 3 6

Fill-倒水问题(Uva-10603-隐式图路径寻找问题)

原题:https://uva.onlinejudge.org/external/106/10603.pdf 有三个没有刻度的杯子,它们的容量分别是a, b, c, 最初只有c中的杯子装满水,其他的被子都是空的.问如果通过倒水得到d升水, 若可以得到,还要求最少的倒水总量(每倒一次水,都加入到总量里).若不能得到d升水,求比d小的距离d最近的d'升水, 及最少倒水总量. 分析: 因为是求最少倒水总量,本能地想到用bfs搜索.最开始读错题了...看成求倒水的最少次数,这个很简单.....我们可以把求

poj3414 Pots(BFS+路径输出)

转载请注明出处:http://blog.csdn.net/u012860063?viewmode=contents 题目链接:http://poj.org/problem?id=3414 此题和poj1606一样 :http://blog.csdn.net/u012860063/article/details/37772275 Description You are given two pots, having the volume of A and B liters respectively.

poj1606 Jugs(BFS+路径输出)

转载请注明出处:http://blog.csdn.net/u012860063?viewmode=contents 题目链接:http://poj.org/problem?id=1606 此题和poj3414一样:http://blog.csdn.net/u012860063/article/details/37768979 Description In the movie "Die Hard 3", Bruce Willis and Samuel L. Jackson were co

POJ-3894 迷宫问题 (BFS+路径还原)

定义一个二维数组: int maze[5][5] = { 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 1, 0, }; 它表示一个迷宫,其中的1表示墙壁,0表示可以走的路,只能横着走或竖着走,不能斜着走,要求编程序找出从左上角到右下角的最短路线. Input 一个5 × 5的二维数组,表示一个迷宫.数据保证有唯一解. Output 左上角到右下角的最短路径,格式如样例所示. Sample Input 0

迷宫bfs+路径记录

给定5*5的地图,1表示墙,0表示空地,从左上角走到左下角 是把所有的可走路径都记录下来了,但是 搜索有递归与非递归形式 本代码使用非递归形式 bfs+路径记录 对于num[i].pre=head的理解是他存在很多条路,每个点是从上一个点走过来的,但总存在一条路是到达终点的,所以,只需要得到到终点的一个head就可以顺着这个路径标记回去了 #include <iostream> #include <cstdio> using namespace std; char a[10][10

HDU 1026 Ignatius and the Princess I(BFS+路径输出)

Ignatius and the Princess I Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 19800    Accepted Submission(s): 6452Special Judge Problem Description The Princess has been abducted by the BEelzebub

POJ 3984:迷宫问题(BFS+路径记录)

迷宫问题 Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 7560   Accepted: 4426 Description 定义一个二维数组: int maze[5][5] = { 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 1, 0, }; 它表示一个迷宫,其中的1表示墙壁,0表示可以走的路,只能横着走或竖着走,不能斜着走,要

HDU 1104 Remainder(BFS路径记录+数论)

Remainder Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 4337    Accepted Submission(s): 1095 Problem Description Coco is a clever boy, who is good at mathematics. However, he is puzzled by a d