广度优先搜索算法

 

学自《ANDROID_2.0游戏开发实战宝典》

 

 

 

 

地图类MapList.java

package com.liangbinny.my;

public class MapList {
    public static int[] source={1,1};//出发点
    public static int[][] target={//目标点坐标数组
        {5,4}
    };
    public static int[][] map = new int[][] //地图数组 , 1表示不可达区域
    {
        {1,1,1,1,1,1,1},
        {1,0,0,0,0,0,1},
        {1,1,0,1,1,0,1},
        {1,1,0,0,1,0,1},
        {1,1,1,1,0,0,1},
        {1,1,1,1,0,1,1},
        {1,1,1,1,1,1,1}
    };
}

 

广搜算法BFS.java

package com.liangbinny.my;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedList;

/**
 * <p><b>
 * 广度优先搜索算法 (breadth first search)
 * 原理是:从原点出发,将所有连接到该原点的结点访问,然后再继续下一层,直到找到目标点
 * 广度优先使用的是队列(LinkedList),先进先出的原理实现广度,
 * 可以这样理解,就是先遍历该原结点的所有相邻结点,进队列,先进先处理,就从广度范围内处理结点
 * 跟栈恰恰相反,而栈刚好用在深度搜索
 * </b></p>
 */
public class BFS {
    int[] source = MapList.source; //出发点
    int[] target = MapList.target[0]; //目标点
    LinkedList<int[][]> queue = new LinkedList<int[][]>(); //广度优先所用队列
    int[][] visited = new int[MapList.map.length][MapList.map[0].length]; //0 未去过 1 去过  , 数组是三维,new的是行数列数
    ArrayList<int[][]> searchProcess = new ArrayList<int[][]>(); //搜索过程
    HashMap<String, int[][]> hm = new HashMap<String, int[][]>(); //结果路径记录
    //这个代表可以移动的8个方向
    int[][] sequence={
        {0,1},{0,-1},
        {-1,0},{1,0},
        {-1,1},{-1,-1},
        {1,-1},{1,1}
    };
    int[][] map = MapList.map;
   
    public void calcBFS(){ //广度搜索优先算法
        //开始状态,这个看作是一条边,开始结点(start[0][0],start[0][1]),另一个结点是(start[1][0],start[1][1])
        int[][] start = {
            {source[0],source[1]},
            {source[0],source[1]}
        };
        queue.offer(start);//入列
        while(true){
            int[][] currentEdge = queue.poll();  //队列取边
            int[] tempTarget = currentEdge[1];  //边的顶点
            //是否已经访问过
            if (visited[tempTarget[1]][tempTarget[0]]==1) {
                continue;
            }
            //标识目的点为访问过
            visited[tempTarget[1]][tempTarget[0]] = 1;
            //记录搜索过程
            searchProcess.add(currentEdge);
            //记录此临时目的点的父节点    (tempTarget[0],tempTarget[1]) 在 currentEdge[1],currentEdge[0] 这个边上
            //最终搜索到显示时,就是根据这个hashmap,从目标点出发,一直往回找寻经过的点
            hm.put(tempTarget[0]+":"+tempTarget[1], new int[][]{currentEdge[1],currentEdge[0]});
            //找到目标
            if (tempTarget[0]==target[0]&&tempTarget[1]==target[1]) {
                break;
            }
            //将该点的所有可能边入队列,根据先进现出规则,就实现了广度搜索
            int currCol = tempTarget[0];
            int currRow = tempTarget[1];
            for (int[] rc : sequence) {  //8个方向都有可能到达
                int i = rc[0];  
                int j = rc[1]; 
                if (currRow+i>=0&&currRow+i<map.length&&currCol+j>=0&&currCol+j<map[0].length&&map[currRow+i][currCol+j]!=1) {
                    int[][] tempEdge = {
                        {tempTarget[0],tempTarget[1]},
                        {currCol+j,currRow+i}
                    };
                    queue.offer(tempEdge);
                }
            }
        }
    }
   
    public static void main(String[] args) {
        BFS bfs = new BFS();
        bfs.calcBFS();  //搜索
        System.out.println("====================广度搜索过程=========================");
        //打印搜索过程路径
        ArrayList<int[][]> list = bfs.searchProcess;
        for (int[][] is : list) {
            System.out.println("start:"+is[0][0]+","+is[0][1]+";end:"+is[1][0]+","+is[1][1]);
        }
       
        System.out.println("====================最终路径=========================");
        //打印最终的结果路径
        //本质是根据搜索路径过程,原着目标点反序,只需要依次找父结点,最后得到的是原点即可
        int[] temp=bfs.target;
        while(true){
            int[][] tempA=bfs.hm.get(temp[0]+":"+temp[1]);
            System.out.println("start:"+tempA[0][0]+","+tempA[0][1]+";end:"+tempA[1][0]+","+tempA[1][1]);
            if(tempA[1][0]==bfs.source[0]&&tempA[1][1]==bfs.source[1]){//判断有否到出发点
                break;
            }
            temp=tempA[1]; 
        }
    }
}

 

 

广度搜索北大acm的例子,本人写的有点烂。

http://poj.org/problem?id=3278

解题代码:

 

import java.util.HashMap;
import java.util.LinkedList;
import java.util.Scanner;

public class Main {
    HashMap<Integer, Integer> hm = new HashMap<Integer, Integer>();
    boolean[] visited = new boolean[200010];
    
    public void calc(int source , int target){
        int[] start = {source,source};
        LinkedList<int[]> queue = new LinkedList<int[]>();
        queue.offer(start);
        while(true){
            int[] currentEdge = queue.poll();
            int tempTarget = currentEdge[1];
            if (visited[tempTarget]) {
                continue;
            }
            visited[tempTarget]=true;
            hm.put(currentEdge[1],currentEdge[0]);
            if (tempTarget==target) {
                break;
            }
            int k1 = tempTarget+1;
            int k2 = tempTarget*2;
            int k3 = tempTarget-1;
            
            if (k1<=100000&&!visited[k1]) {
                queue.offer(new int[]{tempTarget,k1});
            }
            
            if (k2<=100000&&!visited[k2]) {
                queue.offer(new int[]{tempTarget,k2});
            }
            
            if (k3>=0&&!visited[k3]) {
                int[] tempEdge = new int[]{tempTarget,k3};
                queue.offer(tempEdge);
            }
            
        }
    }
    
    public static void main(String[] args) {
        Main test = new Main();
        Scanner cin = new Scanner(System.in);
        int source = cin.nextInt();
        int target = cin.nextInt();
        if (source == target) {
            System.out.println(0);
        }else {
            test.calc(source,target);
            int temp = target;
            int count = 0;
            while(true){
                count++;
                int tempA=test.hm.get(temp);
                if(tempA==source){
                    break;
                }
                temp=tempA;  
            }
            System.out.println(count);
        }
    }
}

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值