2019ソフトウェアエンジニアリングの実践 - 第三の仕事

GitHubのアドレス

https://github.com/wujunjie1008/031702537

P2Pフォーム

PSP2.1 パーソナルソフトウェアプロセス段階 推定時間がかかる(分) 実際の時間がかかる(分)
プランニング 計画 30分 15分
推計 このタスクが必要とどのくらいの時間を見積もります 24時間 26H
開発 開発 5H 2H
分析 (新しい技術を学ぶ含む)ニーズ分析 2H 2H
デザインスペック 設計ドキュメントの生成 15分 30分
デザインレビュー デザインレビュー 1H 30分
標準コーディング コードの仕様(現在の開発のための適切な規範の開発) 10分 15分
設計 具体的な設計 1H 2H
コーディング 具体的なコーディング 4時間 6時間
コードレビュー コードレビュー 2H 4時間
テスト 検査(セルフテスト、コードを変更し、変更を提出) 3H 4時間
報告 レポート 3H 3H
テストrepor テストレポート 30分 1H
サイズ測定 コンピューティングのワークロード 15分 15分
死後&プロセス改善計画 その後まとめ、およびプロセス改善計画 30分 15分
トータル 23.16h 26H

需要

多段数独解決ツールの実現。

数独

数独は、各宮殿が9つの小さなセルに分割され、ディスク9つの宮殿です。デジタル知られており、論理および推論を使用して、この八十から一グリッドを解決する特定の条件を考えると、他の空間に番号1-9を入力します。1-9ので、各番号は、としても知られている各行、各列および各宮殿、一度だけ表示されていることを「正方形」。

初期準備 - 準備作業を速めること

私が前にされているすべての疑問を解決する方法を考えていませんでした。これにより、コードの要件にコマンドパラメータ入力および出力ファイル形式やニーズをCMDに渡されたので、私はBaiduのに行ってきました

int main(int   argc, char*   argv[])

CMDコマンドARGC最初のパラメータの元のmain()関数は、パラメータの入力数に印加され、第2のパラメータはARGV []の文字列は、パラメータに対応され
、所定の入力CMD後の参照私は、パラメータをインポートするためにコードを書きました

    char* i;
    char* o;
    int m, n, h, l;

    m = atoi(argv[2]);
    n = atoi(argv[4]);
    i = argv[6];
    ifstream fin(i);
    if (!fin.is_open())
    {
        cout << "输入文件不存在";
        return 0;
    }
    o = argv[8];
    ofstream fout(o);

入力ファイル:

        h = 0;
        while (!fin.eof()) {            //文件输入
            getline(fin, list);
            if (list.length() != 2 * m && list.length() != 2 * m - 1) {     //表格输入不规范,与阶数m不相符则退出
                cout << "表格大小不符合";
                return 0;
            }
            for (l = 0; l < m; l++) {
                num_list[h][l] = list[l * 2] - 48;
                if (num_list[h][l] < 0 || num_list[h][l]>9) {       //表格输入不规范,出现非数字字符则退出
                    cout << "九宫格中出现不是0-9的数字";
                    return 0;
                }
            }
            h++;

ファイル出力:

        for (h = 0; h < m; h++) {           //文件输出
            for (l = 0; l < m; l++) {
                fout << num_list[h][l];
                if (l != m - 1)
                    fout << ' ';
                else
                    fout << '\n';
            }
        }
        fout << '\n';

問題解決のためのアイデア - マウンテン暗く

私は数独をすれば私にとって個人的に、私は唯一の方法よりを使用して、グリッドの貫通同じ行のスペースは、同じ列に、同じ家の数はどのような数字であり、難しさのために満たすことができることを推測することを好みます数独は、グリッドを埋めることができる唯一のこの番号が記入されている番号を、埋めることができ、別の番号があるだろうスペースがあるだろう、低いですので、私はそれが低いにも適用することができると思います単独の細胞数の難し宮殿の9下位があります。具体的なコードは次のよう:

int weiyu(int m) {
    cout << "使用唯余法" << endl;
    int h, l;
    int may_count;
    int count = 0;
    for (h = 0; h < m; h++) {
        for (l = 0; l < m; l++) {
            if (num_list[h][l] == 0)
                count++;
        }
    }
    for (h = 0; h < m; h++) {
        for (l = 0; l < m; l++) {
            if (num_list[h][l] == 0) {
                int may_num[10] = { 0 };
                may_count = m;
                for (int bh = 0; bh < m; bh++) {        //遍历行
                    if (num_list[bh][l] != 0) {
                        if (may_num[num_list[bh][l]] == 0)
                            may_count--;
                        may_num[num_list[bh][l]] = 1;
                    }
                }
                for (int bl = 0; bl < m; bl++) {        //遍历列
                    if (num_list[h][bl] != 0) {
                        if (may_num[num_list[h][bl]] == 0)
                            may_count--;
                        may_num[num_list[h][bl]] = 1;
                    }
                }
                if (m == 4 || m == 6 || m == 8 || m == 9) {             //遍历宫格
                    int max_h = 0, max_l = 0;
                    int gong_h = 0, gong_l = 0;

                    //定位当前格在属于第几宫格
                    if (m == 4 || m == 8 || m == 9) {
                        gong_l = (int)sqrt(m);
                        gong_h = (int)(m / gong_l);
                    }
                    else if (m == 6) {
                        gong_h = (int)sqrt(m);
                        gong_l = (int)(m / gong_h);
                    }
                    for (int i = 1; i < m; i++) {
                        max_h = i * gong_h;
                        if (max_h > h) {
                            break;
                        }
                    }
                    for (int i = 1; i < m; i++) {
                        max_l = i * gong_l;
                        if (max_l > l) {
                            break;
                        }
                    }

                    //开始遍历
                    for (int i = max_h - gong_h; i < max_h; i++) {
                        for (int j = max_l - gong_l; j < max_l; j++) {
                            if (i > 9)      //消除vs编译器的警告,删去不影响代码
                                i = 9;
                            if (i < 0)
                                i = 0;
                            if (j > 9)
                                j = 9;
                            if (j < 0)
                                j = 0;
                            if (num_list[i][j] != 0) {
                                if (may_num[num_list[i][j]] == 0)
                                    may_count--;
                                may_num[num_list[i][j]] = 1;
                            }
                        }

                    }
                }
                if (may_count == 1) {                   //填写数字
                    for (int i = 1; i <= m; i++) {
                        if (may_num[i] == 0) {
                            num_list[h][l] = i;
                            h = 0;
                            l = -1;
                            count--;                //填写成功,未填数减一
                            if (count == 0) {
                                printf("成功\n");
                                return 0;       //完成数独,返回0
                            }
                            break;
                        }
                    }
                }
            }
        }
    }
    return 1;       //未完成数独,返回1
}

私が行っていたと思っていますが数独パズルの難易度の高いを入力なぜならた後、私は、彼らが下に落ちる感じ。(オリジナルタイトルを添付)
0 0.8 0.9 0 0 0 0
0 7 0 0 0 0 2.8 0
0 6 4 1 0 0 3 0 9
0 0 0 8 0 5 9 0 0
5 0 0 0 0 0 0 0 1
0 0 9 3 0 4 0 0 0
。8 0 2 0 0 7 5 6 0
0 9 7 0 0 0 0 1 0
0 0 0 0 6 0 7 0 0
CD-I法を用いることができるが、溶液が一意でないと、あるいは全くグリッドは魏ゆう法の数が答えを解決できない場合にのみ、満たされていません。単純な数独、塩辛を作るとは差がないことを、私は新しい方法を探し始めました。

問題解決のためのアイデア - 眺め

自閉症は、グリッドが行くしようとする新しい方法の主なテーマは、時間で、私の心は、グリッドを考えることはできませんと思います。その後、人々の周りに耳にDFS(深さ優先アルゴリズム)を話している、私は非常に混乱DFSといくつかのユニークな問題でした。DFS、その後は後に、それは過去に可能なすべてのものを試してみましたがないことが判明しました。私はDFSの時間を実行していますが、それでも心配のヒントを持っています。私は、DFS機能を書き始め、態度を保持してみてください。
-まず、機能を確認し、私はより多くの元、法律の変化だけだ、チェック中()関数が表示されている必要があります。

int check(int h, int l, int m) {
    int num[10] = { 0 };
    for (int bh = 0; bh < m; bh++) {        //遍历行,寻找重复的数字
        if (num_list[bh][l] != 0) {
            num[num_list[bh][l]]++;
            if (num[num_list[bh][l]] > 1)
                return 0;
        }
    }
    for (int i = 0; i < 10; i++) {
        num[i] = 0;
    }
    for (int bl = 0; bl < m; bl++) {        //遍历列,寻找重复的数字
        if (num_list[h][bl] != 0) {
            num[num_list[h][bl]]++;
            if (num[num_list[h][bl]] > 1)
                return 0;
        }
    }
    for (int i = 0; i < 10; i++) {
        num[i] = 0;
    }
    if (m == 4 || m == 8 || m == 9 || m == 6) {         //检验九宫格,寻找重复的数字
        
        //定位该单元格所属的宫格
        int max_h = 0, max_l = 0;                   
        int gong_h = 0, gong_l = 0;
        if (m == 4 || m == 8 || m == 9) {
            gong_l = (int)sqrt(m);
            gong_h = (int)(m / gong_l);
        }
        else if (m == 6) {
            gong_h = (int)sqrt(m);
            gong_l = (int)(m / gong_h);
        }
        for (int i = 1; i < m; i++) {
            max_h = i * gong_h;
            if (max_h > h) {
                break;
            }
        }
        for (int i = 1; i < m; i++) {
            max_l = i * gong_l;
            if (max_l > l) {
                break;
            }
        }
        
        //正式开始遍历
        for (int i = max_h - gong_h; i < max_h; i++) {
            for (int j = max_l - gong_l; j < max_l; j++) {
                if (num_list[i][j] != 0) {
                    num[num_list[i][j]]++;
                    if (num[num_list[i][j]] > 1)
                        return 0;       //有重复,返回0
                }
            }
        }
    }

    return 1;       //无重复,返回1
}

- その後、私たちの主人公DFS(深さ優先探索)関数は次のとおりです。

int DFS(int n, int m){
    if (n > (m*m)) {
        return 1;
    }
    if (num_list[n / m][n % m] != 0){       // 不需要填数字,则跳过
        if (DFS(n + 1, m) == 1)
            return 1;
    }
    else{
        for (int i = 1; i <= m; i++){       //试填1-9的数字 
            num_list[n / m][n % m] = i;
            if (check(n / m, n % m, m) == 1){
                if (DFS(n + 1, m) == 1)
                    return 1;               //返回时如果构造成功,则返回1
                else
                    num_list[n / m][n % m] = 0;
            }
            else
                num_list[n / m][n % m] = 0;
        }
    }
    return 0;
}

私はこのような短いコードで、一見複雑なアイデアを実装することができた後、最終的な結果が成功し、高難易度の数だけでは私だった期待していなかっ獲得しています。
3. 5. 8. 7. 9 2. 1. 4. 6
。9 7 1. 4. 3. 6 2 8 5
2 6 4 1 5 8 3 7 9
7 2 6 8 1 5 9 3 4
5 4 3 6 7 9 8 2 1
。1. 8 9 3 2 。4. 5. 6 7
8 9 1 2 4 5 6 7 3
6 9 8 7 5 4 3 1 2
4 3 1 5 2 6 7 8 9

改善するために探しています

私は、この関数の唯一の法則が削除される前に、部分的にDFSの動作速度の出が保証されていない一方、私は書きたくない、私は彼らの実行時のパフォーマンスを比較プロービング始めたプロファイラーVSが付属しています:

-まず、それは時間だけではDFSの関数である:

-解決策は、時間のDFS機能を使用しない場合に使用する唯一の方法より続く:

私たちもテストかかわらず、問題を見ることができる、唯一の3つの質問には、DFSを使用する必要がありますが、CDを使用しなければなりませんこれは単にため、時間をかけて、より効率的に連動して魏ゆう法とDFSを実証し、DFSを使用するよりもはるかに高速にDFS戦略をファヒータ。

ユニットテスト

ステップ3:

4購入:

5注文:

6順序:

7オーダ:

8順序:

9順序:



概要

この練習の作品を通して、私はいくつかのテストを行い、自分のプロジェクトのために、それを行うだけでなく、そのデバッグのためだけでなく、学んだ、と私は最終的に紹介したような最適化は、DFSアルゴリズムは同じですが、私も学びました私のコードを最適化するために、VS2017プロファイラーのパフォーマンスとコードのセクションの検出を行います。それだけでなく、私も私の時間の合理的な配分であることを学んだ、私は時間との戦いのようにそれを行う、期限がやるようになった4日の距離にあったので、不備を行うには多くの場所は後に、ありますこの仕事はまだ注意が必要です。

おすすめ

転載: www.cnblogs.com/J-J-1008/p/11586587.html