骑士游历(Java课设)
目录
简要解析
回溯法
一解(预见算法、栈实现回溯)
多解(预见算法、栈实现回溯)
全解(回溯,暴力递归)
运行结果图
其他代码
变量
构造函数
判断该点的direction方向是否可走
预见算法
打印路径
打印棋盘
多解的全部代码
end
简要解析
回溯法
回溯法都叫backTrack
一解(预见算法、栈实现回溯)
/*** x[] 走过的方向* dirList 第i层的可选方向* p 点坐标* i 层数* chessboard[][] 记录走法* 需要入栈的变量 : dirList p* 技术难题: dirList的入栈出栈 与使用* 时间复杂度O(n^2*n)=O(n^3) <--> 空间复杂度O(n*n)*/public void backTrack(Point p) //非递归方式的 栈 深度优先 回溯{ //栈如何转化多个分叉的递归int[]x=new int[n*n+1];pathlen=1;int i=1;chessboard[p.x][p.y]=1;LinkedStack<Point> stack=new LinkedStack<>();stack.push(p);SeqList<Integer> dirList;while (p!=null || !stack.isEmpty()) //当前p在i+1层{if(i==n*n){count++;System.out.println("第"+count+"个解");stack.pop();printMat();chessboard[p.x][p.y]=0;i--;break;}dirList=select(p);//对于预见算法select 当到达第24层时,p的下一节点只有一个,而且宽度为0if(x[i]<dirList.size() ) //找到可行解{p=restrict(p,dirList.get(x[i]));x[i]++;i++;pathlen=i;chessboard[p.x][p.y]=i;stack.push(p);}else //没有下一个可行点,回溯{chessboard[stack.peek().x][stack.peek().y] = 0;stack.pop();p=stack.peek();x[i]=0;i--;}}}
多解(预见算法、栈实现回溯)
一个解就是找到一个解就退出循环,结束程序
/*** x[] 走过的方向* dirList 第i层的可选方向* p 点坐标* i 层数* chessboard[][] 记录走法* 需要入栈的变量 : dirList p* 技术难题: dirList的入栈出栈 与使用* 时间复杂度O(n^2*n)=O(n^3) <--> 空间复杂度O(n*n)*/public void backTrack(Point p) //非递归方式的 栈 深度优先 回溯{ //栈如何转化多个分叉的递归int[]x=new int[n*n+1];pathlen=1;int i=1;chessboard[p.x][p.y]=1;LinkedStack<Point> stack=new LinkedStack<>();stack.push(p);SeqList<Integer> dirList;while (p!=null || !stack.isEmpty()) //当前p在i+1层{if(i==n*n){count++;System.out.println("第"+count+"个解");stack.pop();printMat();chessboard[p.x][p.y]=0;i--;
// break;}dirList=select(p);//对于预见算法select 当到达第24层时,p的下一节点只有一个,而且宽度为0if(x[i]<dirList.size() ) //找到可行解{p=restrict(p,dirList.get(x[i]));x[i]++;i++;pathlen=i;chessboard[p.x][p.y]=i;stack.push(p);}else //没有下一个可行点,回溯{chessboard[stack.peek().x][stack.peek().y] = 0;stack.pop();p=stack.peek();x[i]=0;i--;}}}
全解(回溯,暴力递归)
protected void backTrack(int i,Point p)
{if(i<=this.n*this.n){this.pathlen=i;chessboard[p.x][p.y]=i;if(i==this.n*this.n)return;
for(int j=1;j<=8;j++){Point next=restrict(p,j); //八个方向 每个方向都递归if(next!=null) //有下一个位置,则前进到下一个位置{backTrack(i+1,next);
if(i+1==pathlen) //下一步走完 就没有后路了,所以路径终止在p0到p(i+1){if(show){path++;System.out.print("第"+path+"条路径");
}if(i+1==this.n*this.n){count++;System.out.print("第"+count+"个解");System.out.print("时刻:"+(System.currentTimeMillis()-startTime)/1000+"s");System.out.println();list.add(new ChessBoard(chessboard));// this.print(); //输出一条路径/一个解printMat();}
}chessboard[next.x][next.y]=0; //next走完后,退回到前一个递归函数的状态,走下一个next方向}}}
}
运行结果图
其他代码
变量
protected final int n; //棋盘规格为 n*n
protected int chessboard[][];
protected boolean show;
protected int pathlen,path,count;
构造函数
public Knight_Stack(int n, int x, int y, boolean show)
{if(n>=3 && n<=50)this.n = n;elsethrow new IllegalArgumentException("n="+n);chessboard=new int[n][n]; //初始值为0System.out.println("n="+n+",point="+new Point(x,y));this.show=show;pathlen=0;path=0;count=0;
// backTrack(1,new Point(x,y)) ; //递归backTrack(new Point(x,y)); //栈System.out.println("共有"+count+"个解");
}
判断该点的direction方向是否可走
protected Point restrict(Point point,int direction){int x=point.x,y=point.y;switch(direction){case 1:x-=2 ;y++; break;case 2:x--; y+=2;break;case 3:x++; y+=2;break;case 4:x+=2; y+=1;break;case 5:x+=2; y--; break;case 6:x+=1; y-=2;break;case 7:x-=1; y-=2;break;case 8:x-=2; y-=1;break;}if(x>=0 && x<this.n && y>=0 && y<this.n && this.chessboard[x][y]==0)return new Point(x,y); //0表示还没有经过,没有走过return null;}
预见算法
protected SeqList<Integer> select(Point p) //返回大小为n的线性表,方向按照 路的“宽度”从小到大存放{ //求得下一步8个方向位置的路的“宽度”,并将元素从大到小拍放在线性表,,不如排序线性表。。if(show){System.out.println("当前点为:" + p);// print();//打印当前路径printMat();}
// 计算宽度,以当前点为下一节点,计算自己可走的路数Point next;int minRoad=8;SeqList<Integer> list=new SeqList<>();for(int k=1;k<=8;k++) //选择宽度最小的方向,并且将宽度最小的方向{int avl = 0;next=restrict(p,k);if(next!=null && chessboard[next.x][next.y]==0) //下一步,不仅要有,还得时未走过的{for (int i = 1; i <= 8; i++)if (restrict(next, i) != null)avl++;if(avl<minRoad){minRoad=avl;list.clear();}if(avl==minRoad)list.insert(k);}}return list;}
打印路径
protected void print() //输出路径 从点(x,y)开始{String str="[";for(int k=1;k<=n*n;k++)for(int i=0;i<n;i++)for(int j=0;j<n;j++){if(chessboard[i][j]==k) //得到顺序路径上的一点p(i,j)str+=new Point(i,j)+",";}if(str.length()>1)str=str.substring(0,str.length()-1);System.out.println(str+"]");}
打印棋盘
private void printMat(){for (int i=0;i<n;i++){for (int j = 0; j < n; j++)System.out.printf("%5d",chessboard[i][j]);System.out.println();}}
多解的全部代码
package chapter_10_courseDesign;import chapter_1_1_SeqLIst.SeqList;
import chapter_3_1_Stack_Queue.LinkedStack;public class Knight //二维数组chessBoard存储n*n棋盘的一个解,使用预见算法 回溯算法
{protected final int n; //棋盘规格为 n*nprotected int chessboard[][];protected boolean show;protected int pathlen,path,count;public Knight(int n, int x, int y, boolean show){if(n>=3 && n<=12)this.n = n;elsethrow new IllegalArgumentException("n="+n);chessboard=new int[n][n]; //初始值为0System.out.println("n="+n+",point="+new Point(x,y));this.show=show;pathlen=1;path=0;count=0;
// backTrack(1,new Point(x,y));backTrack(new Point(x,y));System.out.println("共有"+count+"个解");}/*** x[] 走过的方向* dirList 第i层的可选方向* p 点坐标* i 层数* chessboard[][] 记录走法* 需要入栈的变量 : dirList p* 技术难题: dirList的入栈出栈 与使用* 时间复杂度O(n^2*n)=O(n^3) <--> 空间复杂度O(n*n)*/public void backTrack(Point p) //非递归方式的 栈 深度优先 回溯{ //栈如何转化多个分叉的递归int[]x=new int[n*n+1];pathlen=1;int i=1;chessboard[p.x][p.y]=1;LinkedStack<Point> stack=new LinkedStack<>();stack.push(p);SeqList<Integer> dirList;while (p!=null || !stack.isEmpty()) //当前p在i+1层{if(i==n*n){count++;System.out.println("第"+count+"个解");stack.pop();printMat();chessboard[p.x][p.y]=0;i--;
// break;}dirList=select(p);//对于预见算法select 当到达第24层时,p的下一节点只有一个,而且宽度为0if(x[i]<dirList.size() ) //找到可行解{p=restrict(p,dirList.get(x[i]));x[i]++;i++;pathlen=i;chessboard[p.x][p.y]=i;stack.push(p);
// dirStack.push(dirList);}else //没有下一个可行点,回溯{chessboard[stack.peek().x][stack.peek().y] = 0;stack.pop();
// dirStack.pop();p=stack.peek();x[i]=0;i--;}}}protected void backTrack(int i,Point p){if(i<=this.n*this.n){this.pathlen=i;chessboard[p.x][p.y]=i;if(i==this.n*this.n) //到达叶子节点,直接返回,回溯return;SeqList<Integer> direList=this.select(p); //预见算法给出的方向选择for(int j=0;j<direList.size();j++){Point next=restrict(p,direList.get(j));if(next!=null) //有下一个位置,则前进到下一个位置{backTrack(i+1,next);if(i+1==pathlen) //下一步走完 就没有后路了,所以路径终止在p0到p(i+1){if(show){path++;System.out.print("第"+path+"条路径");}if(i+1==this.n*this.n){count++;System.out.print("第"+count+"个解");}System.out.println();printMat();}chessboard[next.x][next.y]=0; //next点走完后,退回到前一个递归函数的状态,走下一个next方向}}}}protected void print() //输出路径 从点(x,y)开始{String str="[";for(int k=1;k<=n*n;k++)for(int i=0;i<n;i++)for(int j=0;j<n;j++){if(chessboard[i][j]==k) //得到顺序路径上的一点p(i,j)str+=new Point(i,j)+",";}if(str.length()>1)str=str.substring(0,str.length()-1);System.out.println(str+"]");}private void printMat(){for (int i=0;i<n;i++){for (int j = 0; j < n; j++)System.out.printf("%3d",chessboard[i][j]);System.out.println();}}protected SeqList<Integer> select(Point p) //返回大小为n的线性表,方向按照 路的“宽度”从小到大存放{ //求得下一步8个方向位置的路的“宽度”,并将元素从大到小拍放在线性表,,不如排序线性表。。if(show){System.out.println("当前点为:" + p);print();//打印当前路径
// printMat();}
// 计算宽度,以当前点为下一节点,计算自己可走的路数Point next;int minRoad=8;SeqList<Integer> list=new SeqList<>();for(int k=1;k<=8;k++) //选择宽度最小的方向,并且将宽度最小的方向{int avl = 0;next=restrict(p,k);if(next!=null && chessboard[next.x][next.y]==0) //下一步,不仅要有,还得时未走过的{for (int i = 1; i <= 8; i++)if (restrict(next, i) != null)avl++;if(avl<minRoad){minRoad=avl;list.clear();}if(avl==minRoad)list.insert(k);}}return list;}protected Point restrict(Point point,int direction){int x=point.x,y=point.y;switch(direction){case 1:x-=2 ;y++; break;case 2:x--; y+=2;break;case 3:x++; y+=2;break;case 4:x+=2; y+=1;break;case 5:x+=2; y--; break;case 6:x+=1; y-=2;break;case 7:x-=1; y-=2;break;case 8:x-=2; y-=1;break;}if(x>=0 && x<this.n && y>=0 && y<this.n && this.chessboard[x][y]==0)return new Point(x,y); //0表示还没有经过,没有走过return null;}public static void main(String[] args){long start=System.currentTimeMillis();Knight knight=new Knight(5,0,0,true);System.out.println("用时"+(System.currentTimeMillis()-start)+"ms");}
}
end
骑士游历(Java课设)相关推荐
- 【源码+教程】Java课设项目_12款最热最新Java游戏项目_Java游戏开发_Java小游戏_飞翔的小鸟_王者荣耀_超级玛丽_推箱子_黄金矿工_贪吃蛇
马上就要期末了,同学们课设做的如何了呢?本篇为大家带来了12款热门Java小游戏项目的源码和教程,助力大家顺利迎接暑假![源码+教程]Java课设项目_12款最热最新Java游戏项目_Java游戏开发 ...
- java 课设 商品库存管理系统
比较辛苦的java课设!写了蛮久的,战斗了好多个通宵. 下载https://download.csdn.net/download/qq_37871063/10297290 入门:JAVAFX+MVC+ ...
- 华南农业大学课设——数据结构课设、Java课设、操作系统课设
文章目录 缘起 大二上-数据结构课设(高校教学管理系统)-C++.Qt 视频演示 感想 大二下-Java课设(流程图绘制程序)-JavaFX 视频演示 感想 大三上-操作系统课设(模拟磁盘文件系统实现 ...
- 学生信息管理系统(成绩统计)Java课设
下载地址:学生信息管理系统(成绩统计)Java课设-Web服务器文档类资源-CSDN下载 ├── StudentInfo │ ├── bin │ │ ├── com │ │ │ ...
- JAVA课设单人版五子棋小游戏
内容介绍:该程序为Java课设的单人版五子棋小游戏,通过eclipse编辑,实现了动作事件的监听与处理,以及JavaSwing的界面编程. 编辑排行榜,包含局数,结果,步数,以及"关于我们 ...
- Java课设——ArxivHelper
项目地址https://github.com/PKUCSS/arxiv-helper How to run运行方式:java -jar arxiv-helper.jar Tips:We use pyi ...
- 100套java课设源码参考/毕设源码代码参考
引言:本人是一个Java 开发者,喜欢分享Java课设源码和代码,用于课程设计或者作业学习参考噢,开发一些有技术含量的Java web源码,主要的技术有JSP+Servlet,SSM/SpringBo ...
- JAVA课设:电子英汉词典(附源码+调试)
JAVA课设:电子英汉词典 电子英汉词典功能概述 整体要求:用图形用户界面实现,能够编辑词典库中的信息,能够实现英译汉,汉译英.(要考虑一词多义) 具体实现:1.用图形用户界面实现:2.能够实现英译汉 ...
- 【Java课设】--ATM取款机(Gui界面)
[Java课设]–ATM取款机(Gui界面)
最新文章
- OO第三单元作业总结
- Android之linux基础教学之七 中断下半部之软中断
- P1417 烹调方案 (0/1背包+贪心)
- LeetCode 872叶子相似的树-简单
- [Oracle]如何查看一个数据文件是否是自动扩展
- 【文智背后的奥秘】系列篇——分布式爬虫之WebKit
- 开源demo| 视频应用类开源 Demo 大盘点
- Matlab数据库工具箱的简单使用
- python字体和图片合成
- [BUG 记录] Ubuntu下Tesla M40与其他N卡共存安装
- 纯css写滚动的弹幕特效
- “华为“和“荣耀”区别日益明显,荣耀传递潮流价值观
- 如何创建XS Job来完成定时任务
- Booting ARM Linux
- Python机器学习、深度学习库总结
- 有五万块钱,在农村养牛怎么样?能养多少头牛?
- Weblogic常见报错以及解决方法[转载]
- 有关数据包拓展基础知识
- 早期的行人再识别与深度行人再识别研究——行人再识别技术综述阅读笔记
- 自定义 SAP 采购订单屏幕