柔軟な労働慣行第3の動作
0.Githubアドレス
https://github.com/muke2000/031702418
1.PSPテーブル
パーソナルソフトウェアプロセス段階 | 推定時間がかかる(分) | 実際の時間がかかる(分) |
---|---|---|
計画 | 30 | 20 |
このタスクが必要とどのくらいの時間を見積もります | 10 | 10 |
開発 | 200 | 150 |
(新しい技術を学ぶ含む)ニーズ分析 | 60 | 40 |
設計ドキュメントの生成 | 60 | 60 |
デザインレビュー | 30 | 20 |
コードの仕様(現在の開発のための適切な規範の開発) | 10 | 10 |
具体的な設計 | 40 | 30 |
具体的なコーディング | 120 | 180 |
コードレビュー | 30 | 20 |
検査(セルフテスト、コードを変更し、変更を提出) | 400 | 180 |
レポート | 60 | 30 |
テストレポート | 60 | 40 |
コンピューティングのワークロード | 30 | 15 |
その後まとめ、およびプロセス改善計画 | 60 | 40 |
トータル | 1300 | 845 |
2.問題解決のアイデア
看到题目为解数独,且最大宫数为9时我便决定用深度优先搜索直接搜索出解。
3.設計プロセス
由于本题只是一道算法题,于是我便决定只设计一个类来求解,该类主要由main函数、输入输出函数、判断函数、深度优先搜索函数组成。
3.0入出力機能
パラメータを読み出し、N、Mは、ディスクが各コールを停止のみ出力関数溶液に直接入力され、いくつかのディスクを入力すると判定され
public static void inAndOut(int n,String in,String out,int m) throws IOException {
File input = new File(in);
File output = new File(out);
BufferedReader reader = null;
BufferedWriter writer = null;
reader = new BufferedReader(new FileReader(input));
writer = new BufferedWriter(new FileWriter(output));
for(int l=0;l<n;l++){//l表示当前读到第几盘
for(int i=0;i<m;i++){
String s = reader.readLine();//读入该行
String str = s.replace(" ","");//删除空格
for(int j=0;j<m;j++){
char [] chars = str.toCharArray();//char转为int
array[i][j] = chars[j]-48;
}
}
if(dfs(0,m)){
for(int i=0;i<m;i++){
for(int j=0;j<m;j++){
writer.write(array[i][j]+" ");
}
writer.newLine();//写入新的一行
}
}else {
writer.write("no result");
}
writer.newLine();
String s = reader.readLine();
}
writer.close();
}
3.1判定する機能
同じことが、空白で埋めることができない場合は、スペースを埋めるためにしたい位置に応じて、数は、対応する空と比較して、デジタルのランクと家を埋めるしようとしています
private static boolean isIn(int n,int x,int y,int m){
for(int i=0;i<m;i++){
if(array[x][i]==n||array[i][y]==n)//判断与该行该列的数字是否相同
return false;
}
if(m==9) {//宫数为9时判断与该宫内的数字是否相同
for (int i = (x / 3) * 3; i < (x / 3 + 1) * 3; i++) {
for (int j = (y / 3) * 3; j < (y / 3 + 1) * 3; j++) {
if (array[i][j] == n)
return false;
}
}
}
if (m==4){//宫数为4时判断与该宫内的数字是否相同
for (int i = (x / 2) * 2; i < (x / 2 + 1) * 2; i++) {
for (int j = (y / 2) * 2; j < (y / 2 + 1) * 2; j++) {
if (array[i][j] == n)
return false;
}
}
}
if(m==6) {//宫数为6时判断与该宫内的数字是否相同
for (int i = (x / 2) * 2; i < (x / 2 + 1) * 2; i++) {
for (int j = (y / 3) * 3; j < (y / 3 + 1) * 3; j++) {
if (array[i][j] == n)
return false;
}
}
}
if(m==8) {//宫数为8时判断与该宫内的数字是否相同
for (int i = (x / 4) * 4; i < (x / 4 + 1) * 4; i++) {
for (int j = (y / 2) * 2; j < (y / 2 + 1) * 2; j++) {
if (array[i][j] == n)
return false;
}
}
}
return true;
}
3.2深さ優先探索機能
空間の最初の列の最初の行から順番は、満たされないようなテスト機能配列で9に1から空の又は検査をスキップするデジタルスペースとして、検索を開始するために、プロセスはに返さ空の上で、再帰の最後まで空81を埋めます。次のように私は、関数定義がvoid DFS機能タイプで書き始め
public static void dfs(int x,int m){
if (x == (m*m)) {//如果以填完最后一空返回
return;
}
int i = x / m;
int j = x % m;
if (array[i][j] == 0) {
for (int k = 1; k <= m; k++) {
if (isIn(n,i,j,m) {//该数字没有重复,可以填入
array[i][j] = k;
dfs(x + 1,m);//继续填下一空
}
array[i][j] = 0;//清除掉刚填过的数字,将盘面退回原样
}
} else {
dfs(x + 1,m);//继续填下一空
}
}
このコードは、入力ファイルとまったく同じで、出力ファイルの後に実行されます、そして、私はブログで他の人のコードは、深さ優先探索で論理と、私のような、しかし結果は置く出力は最後のスペースに到達し、あなたは正しい結果を得ることができた参照します上記のように、コードの違い
public static void dfs(int k,int m,String outputFilename) throws IOException {
if (k == (m*m)) {
try{//直接将结果输出
File output = new File(outputFilename);
BufferedWriter writer = null;
writer = new BufferedWriter(new FileWriter(output));
for(int i=0;i<m;i++){
for(int j=0;j<m;j++){
writer.write(table[i][j]+" ");
}
writer.newLine();
}
writer.newLine();
writer.close();
}
catch (Exception e) {
e.printStackTrace();
}
return;
}
int x = k / m;
int y = k % m;
if (table[x][y] == 0) {
for (int i = 1; i <= m; i++) {
table[x][y] = i;
if (judge(table,x, y, i,m)) {
dfs(k + 1,m,outputFilename);
}
}
table[x][y] = 0;
} else {
dfs(k + 1,m,outputFilename);
}
}
だから私はそこに81の空、再帰関数に到達した後、何もタイムリーに出力されていないと解消される準備が満載のスペースで、その結果、以前の状態に戻って後退しているので、それがある疑いがあるので、私は完成を防ぐために、ディスクを格納するための配列を追加しました次のように空気が、空にされます
public static int [][] res = new int[9][9];
public static void dfs(int num,int m)
{
if(num==m*m){//将数组保存到另一个新数组,并返回
for(int i=0; i<m; i++){
for(int j=0; j<m; j++)
res[i][j]=array[i][j];
}
return ;
}
int i=num/m,j=num%m;
if(array[i][j]!=0) dfs(num+1,m);
else{
for(int k=1; k<=m; k++)
{
if(isIn(k,i,j,m))
{
array[i][j]=k;
dfs(num+1,m);
}
}
array[i][j]=0;
}
return ;
}
この時間は、正確な数独を解決してきたが、私がテストしたときに、私は複数のソリューションのためのユニークなソリューションの数ならば数が大きい場合、コードは関数が常になりますので、結果には非常に長い時間を実行する必要があることがわかりましたすべての場合は結果になりトラバースし、大きなメモリ空間を必要とするので、私は最初のソリューションに至るには、フォームにDFS機能を取っされて、直接、次のコードを返すことができます
public static boolean dfs(int x,int m){
int i,j;
i = x/m;j = x%m;
if(x==m*m){//如过已填完最后一空则返回true
return true;
}
if(array[i][j]!=0) return dfs(x+1,m);//继续填下一空
for(int n=1;n<=m;n++){
if(isIn(n,i,j,m)){
array[i][j] = n;
if(dfs(x+1,m)) return true;//如果下一空结果正确则返回true;
array[i][j] = 0;//如果下一空没有可以填入的数字则应清除该空以填入的数据,填入下一个可用数字
}
}
return false;//该空找不到可以填入的数字,返回false以返回到上一空
}
関数は、その結果を出力初めてブールに設定することができ、最後に空に到達することができ、返すかどうかを決定するために、戻り値前の状態に応じた値を返します。
改善のための4つの方法
主なアイデアは3.2深さ優先探索機能の上部に反映することです。
テスト設計部
私のテストユニットは、3つのステップに分割され
、最初のステップは、テストの入出力部であり
、第二のステップは解決するために、単独で、部品点数を試験することである、なぜならC ++より身近で、IはCで実現するために開始++アルゴリズムを使用します唯一移植Javaの後に、
第3のステップは、試験のための完全なコードの前の二つの部分を統合することです。
6.考え方と収穫
操作は、私にとって主な困難は、深さ優先探索の機能設計で、比較的簡単ですが、この割り当ては深さ優先探索と再帰の私の理解を深めますが、どのように非常に役立つソフトウェアを構築しないように。