学自《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);
}
}
}