软工实践3

GitHub地址

GitHub

PSP表格

PSP2.1 Personal Software Process Stages 预估耗时(分钟) 实际耗时(分钟)
Planning 计划 30 20
Estimate 估计这个任务需要多少时间 20 20
Development 开发 120 90
Analysis 需求分析 (包括学习新技术) 240 200
Design Spec 生成设计文档 30 40
Design Review 设计复审 10 10
Coding Standard 代码规范 (为目前的开发制定合适的规范) 20 10
Design 具体设计 60 80
Coding 具体编码 300 120
Test 测试(自我测试,修改代码,提交修改) 120 540
Reporting 报告 30 0
Test Repor 测试报告 30 0
Size Measurement 计算工作量 10 20
Postmortem & Process Improvement Plan 事后总结, 并提出过程改进计划 20 10
合计 1040 1180
作业历程

刚拿到题目觉得算法方面要想解决问题不大,在网上简单搜索后采用了深搜以及回溯剪枝,指定完初步计划后,每天空余时间对算法做初步构思,因此编码过程还是挺快的。觉得进度赶得上,决定用java完成本次作业,一切从helloworld开始。然而还是太年轻,在IO流上踢到铁板,参考了各位大佬以及网上各路神仙的文章,两天一夜仍未解决,最后求助助教才仓促收篇。计划赶不上变化,基础的不扎实以及对时间的错误预估,性能分析的环节未能展开。

解题思路&代码模块

cmd参数解析

 static void loadArgs (String[] args)
		{	
			if(args.length > 0 && args != null) {				
				for (int i=0;i<args.length;i++) {
				switch(args[i]) {
				case"-i":
					inputFileName = args[++i];
					break;
				case"-o":
					outputFileName = args[++i];
					break;
				case"-m":
					m = Integer.valueOf(args[++i]);
					break;
				case"-n":
					n = Integer.valueOf(args[++i]);
					break;
				default:
					break;
				}
				}
			}
		}
	 

文件输入输出

开始的时候都采用全局变量,导致文件写入只能运算一盘数独。后期改回来后又在IO流上出了问题,文件输入输出只能草草结尾。这部分内容未完待续…

	 public static void main(String [] args) {			 
		loadArgs(args);
		File src = new File("E:/Java/project/031702241/src/input.txt");
		rank = m;
		int shudu[][]=new int[k][k];
		 
		try {
			FileReader file = new FileReader(src);
			BufferedReader buff = new BufferedReader(new FileReader(src));
			PrintWriter out = new PrintWriter ("E:/Java/project/031702241/src/output1.txt");
			String linenum  = null;
			int p=0,q=0,r=0;
			while((linenum=buff.readLine())!=null) {
				if(!linenum.equals(""))
				{
					String[] inputstring = linenum.split("");
					for(q=0;q<m;q++)
						shudu[p][q]=Integer.parseInt(inputstring[q]);
					p++;r++;
				}
				if(r==m) {
				//sudoku.scanf();
				int [][] line   = new  int[k][k];
				int [][] row    = new  int[k][k];
				int [][] square = new  int[k][k];
				int t=0;
					for (int i=1;i<=rank;i++)
						for(int j=1;j<=rank;j++)
						{
							line[i][shudu[i][j]]=1;						//行、列、宫输入
							row[j][shudu[i][j]]=1;
						
							if(rank!=3||rank!=5||rank!=7)
							{
								t=square(i,j);
								square[t][shudu[i][j]]=1;
							}
						}
				dfs(1, 1,shudu,line,row,square);
				//sudoku.print();
				for (int i=1;i<=rank;i++)
				{				
					for(int j=1;j<=rank;j++)
					{
						 out.print(shudu[i][j]+" ");	
					}
						 out.println();				
				}
				 out.println();
				
				p=0;r=0;
				}
		}	
		out.flush();
		file.close();
		buff.close();
		out.close();
	 }catch(IOException r) {
		 r.printStackTrace();
	 }
}

核心算法

DFS深搜&回溯剪枝
网上较常见的解决方案。编码过程直接从九宫格开始考虑,分行、列、宫进行唯一性检测,分别用三个数组进行标记完成回溯剪枝。

public static boolean dfs(int x,int y,int[][]shudu,int[][]line,int[][]row,int[][]square)		//方法 深度优先搜索+回溯
	 {
		 if(x==rank&&y==rank)					//最后一个格子 结束
			 return true;
		 int flag=0;
		 for(;x<=rank;x++)						//判断是否为待填空
		 {
			 flag=0;
			 for(;y<=rank;y++)
				 if (shudu[x][y]==0)
				 {
					 flag=1;
					 break;
				 }
			 if(flag==1) 
				 break;
			 else y=1;
		 }										//判断结束
	
		int t=0;
		 for (int s=1;s<=rank;s++)									//循环9个数字 逐一排除 s=当前筛选的数字
		 {	
			 t=square(x,y);											//t=宫号
			 if(rank==3||rank==5||rank==7) square[t][s]=0;
			 if(line[x][s]==0 && row[y][s]==0 && square[t][s]==0)	//行、列、宫是否符合规则
			 {
				 line[x][s]=1;										//行、列、宫标记
				 row [y][s]=1;
				 shudu[x][y]=s;
				 if(rank!=3||rank!=5||rank!=7)						//3、5、7阶不需要判断宫
					 square[t][s]=1;			
				 
				 if(dfs(x,y,shudu,line,row,square)==true)									//DFS嵌套  =false回溯
					 return true;
				 
				 line[x][s]=0;										//行、列、宫取消标记
				 row [y][s]=0;	
				 shudu[x][y]=0;
				 if(rank!=3||rank!=5||rank!=7)
					 square[t][s]=0;
			 }
		 }
		 return false;
	 }

单元测试

posted @ 2019-09-25 22:43  JasonL-S  阅读(168)  评论(2编辑  收藏  举报