马踏棋盘算法
- 优化前的原始算法
首先假设具体一种情况进行分析设计
具体算法
public class HorseChessBoard {
//二维数组,表示棋盘
private static int X = 6;//表示列col
private static int Y = 6;//表示行row
private static int[][] chessBoard = new int[Y][X];//棋盘
private static boolean[] visited = new boolean[X * Y];//记录某个位置是否走过
private static boolean finished = false;//记录马儿是否遍历完数组了
public static void main(String[] args) {
//马儿当前位置
int row = 3;//行
int col = 1;//列
//调用方法
System.out.println("开始....");
long start = System.currentTimeMillis();
traversalChessBoard(chessBoard,row - 1, col - 1 , 1);
long end = System.currentTimeMillis();
System.out.println("耗时 = " + (end - start));
//先输出一下棋盘
for (int[] rows : chessBoard) {
for (int step : rows) {
System.out.print(step + "\t");
}
System.out.println();
}
}
//体验大厂的算法题 => 算法发的魅力
//该方法,可以获取到当前位置,可以走的下一步的所有位置
public static ArrayList<Point> next(Point curPoint) {
//创建给Arraylist
ArrayList<Point> ps = new ArrayList<Point>();
//创建一个Point 准备放入到ps
Point p1 = new Point();
//判断5是否可以走,如果可以走,就加入到ps
if ((p1.x = curPoint.x - 2) >= 0 && (p1.y = curPoint.y - 1) >= 0) {
ps.add(new Point(p1));
}
//判断6是否可以走
if ((p1.x = curPoint.x - 1) >= 0 && (p1.y = curPoint.y - 2) >= 0) {
ps.add(new Point(p1));
}
//判断7是否可以走
if ((p1.x = curPoint.x + 1) < X && (p1.y = curPoint.y - 2) >= 0) {
ps.add(new Point(p1));
}
//判断0是否可以走
if ((p1.x = curPoint.x + 2) < X && (p1.y = curPoint.y - 1) >= 0) {
ps.add(new Point(p1));
}
//判断1是否可以走
if ((p1.x = curPoint.x + 2) < X && (p1.y = curPoint.y + 1) < Y) {
ps.add(new Point(p1));
}
//判断2是否可以走
if ((p1.x = curPoint.x + 1) < X && (p1.y = curPoint.y + 2) < Y) {
ps.add(new Point(p1));
}
//判断3是否可以走
if ((p1.x = curPoint.x - 1) >= 0 && (p1.y = curPoint.y + 2) < Y) {
ps.add(new Point(p1));
}
//判断4是否可以走
if ((p1.x = curPoint.x - 2) >= 0 && (p1.y = curPoint.y + 1) < Y) {
ps.add(new Point(p1));
}
return ps;
}
//核心算法代码,完成马儿遍历棋盘
public static void traversalChessBoard(int[][] chessBoard, int row, int col,int step){
//先把当前这个点的第几步记录
chessBoard[row][col] = step;
//把这个位置记录为已经访问
visited[row * X + col] = true;
//获取当前这个位置可以走的下一个位置
ArrayList<Point> ps = next(new Point(col, row));
//遍历
while (!ps.isEmpty()){
//取出一个位置
Point p = ps.remove(0);
//判断该位置是否走过,如果没有走,可以就递归遍历
if (!visited[p.y * X + p.x]){
//递归遍历
traversalChessBoard(chessBoard,p.y,p.x, step + 1);
}
}
//当退出while循环后,看看是否遍历成功,如果没有成功,则重置相应值,然后进行回溯
if (step < X * Y && !finished){
//重置
chessBoard[row][col] = 0;
visited[row * X + col] = false;
}else {
finished = true;
}
}
}
算法运行结果
2 该算法存在一定的局限性,如果初始位置为某一特殊位置时,程序运行及其缓慢,比如所如下情况
//马儿当前位置
int row = 2;//行
int col = 2;//列
此时程序运行时间让人怀疑
3.针对这种情况,我们应该采用一定的优化机制,比如以下就是采用贪心算法优化后的程序,效率大大提高了
public class HorseChessBoard {
//二维数组,表示棋盘
private static int X = 6;//表示列col
private static int Y = 6;//表示行row
private static int[][] chessBoard = new int[Y][X];//棋盘
private static boolean[] visited = new boolean[X * Y];//记录某个位置是否走过
private static boolean finished = false;//记录马儿是否遍历完数组了
public static void main(String[] args) {
//马儿当前位置
int row = 2;//行
int col = 2;//列
//调用方法
System.out.println("开始....");
long start = System.currentTimeMillis();
traversalChessBoard(chessBoard,row - 1, col - 1 , 1);
long end = System.currentTimeMillis();
System.out.println("耗时 = " + (end - start));
//先输出一下棋盘
for (int[] rows : chessBoard) {
for (int step : rows) {
System.out.print(step + "\t");
}
System.out.println();
}
}
//体验大厂的算法题 => 算法发的魅力
//该方法,可以获取到当前位置,可以走的下一步的所有位置
public static ArrayList<Point> next(Point curPoint) {
//创建给Arraylist
ArrayList<Point> ps = new ArrayList<Point>();
//创建一个Point 准备放入到ps
Point p1 = new Point();
//判断5是否可以走,如果可以走,就加入到ps
if ((p1.x = curPoint.x - 2) >= 0 && (p1.y = curPoint.y - 1) >= 0) {
ps.add(new Point(p1));
}
//判断6是否可以走
if ((p1.x = curPoint.x - 1) >= 0 && (p1.y = curPoint.y - 2) >= 0) {
ps.add(new Point(p1));
}
//判断7是否可以走
if ((p1.x = curPoint.x + 1) < X && (p1.y = curPoint.y - 2) >= 0) {
ps.add(new Point(p1));
}
//判断0是否可以走
if ((p1.x = curPoint.x + 2) < X && (p1.y = curPoint.y - 1) >= 0) {
ps.add(new Point(p1));
}
//判断1是否可以走
if ((p1.x = curPoint.x + 2) < X && (p1.y = curPoint.y + 1) < Y) {
ps.add(new Point(p1));
}
//判断2是否可以走
if ((p1.x = curPoint.x + 1) < X && (p1.y = curPoint.y + 2) < Y) {
ps.add(new Point(p1));
}
//判断3是否可以走
if ((p1.x = curPoint.x - 1) >= 0 && (p1.y = curPoint.y + 2) < Y) {
ps.add(new Point(p1));
}
//判断4是否可以走
if ((p1.x = curPoint.x - 2) >= 0 && (p1.y = curPoint.y + 1) < Y) {
ps.add(new Point(p1));
}
return ps;
}
//该方法可以对ps的位置进行排序,把可能走的下一个位置,从小到大排序
public static void sort(ArrayList<Point> ps){
ps.sort(new Comparator<Point>() {
@Override
public int compare(Point o1, Point o2) {
return next(o1).size() - next(o2).size();
}
});
}
//核心算法代码,完成马儿遍历棋盘
public static void traversalChessBoard(int[][] chessBoard, int row, int col,int step){
//先把当前这个点的第几步记录
chessBoard[row][col] = step;
//把这个位置记录为已经访问
visited[row * X + col] = true;
//获取当前这个位置可以走的下一个位置
ArrayList<Point> ps = next(new Point(col, row));
//使用贪心算法优化
sort(ps);
//遍历
while (!ps.isEmpty()){
//取出一个位置
Point p = ps.remove(0);
//判断该位置是否走过,如果没有走,可以就递归遍历
if (!visited[p.y * X + p.x]){
//递归遍历
traversalChessBoard(chessBoard,p.y,p.x, step + 1);
}
}
//当退出while循环后,看看是否遍历成功,如果没有成功,则重置相应值,然后进行回溯
if (step < X * Y && !finished){
//重置
chessBoard[row][col] = 0;
visited[row * X + col] = false;
}else {
finished = true;
}
}
}
程序运行结果