第三次軟件工程實踐做業

個人GitHub:mmbhwhhpython

PSP

PSP 預估耗時(小時) 實際耗時(小時)
計劃 2 3
估計這個任務須要多少時間 16 20
開發 1 2
需求分析 (包括學習新技術) 2 2
生成設計文檔 2 3
設計複審 3 3
具體設計 2 3
具體編碼 3 5
代碼複審 3 3
測試(自我測試,修改代碼,提交修改) 1 2
報告 2 3
過程改進計劃 1 2
總計 22 31

思考

開始拿到題目的時候,覺得是我想象中的數獨,就簡單的想着只要把每一個已經肯定的數對它當前所在的行、列、宮格的影響擴散出去,題目又說給的數獨都是惟一解的,這更加讓我確信用個人思路能夠解出來,而後就試了試。git

剛開始的思路

大致和第一位交做業的莫多同窗同樣,就是對數獨遍歷兩次,第一次找到入口(由於題目說測試的數據都是惟一解),找到一個肯定的點,而後將它的影響擴散給行、列、宮格,最終就會將整個表格填滿。寫了好久的代碼,卻發現個人思路只能填寫一部分數據,沒玩過數獨的我仍是太嫩了,後面冷靜下來思考一番,若是數獨有這麼簡單還叫什麼數獨呢,從個人那些錯誤的數據我知道了,儘管一個數獨只有一個解,可是它也不必定能夠用邏輯直接肯定所有的值,由於我從我錯誤的代碼打出來的錯誤結果顯示,沒填的那部分數據的確不能肯定,必需要填入數值進去試探,雖然填的數字合法,可是解不出來。這結果讓我原地自閉。github

第二次想法

經歷了上次的教訓,索性直接用暴力的辦法解這道題。思路就是從第一個格子一直找到最後一個格子,若是找到了空格子,那就給它賦上合法的數值,而後繼續找,若是找不到了就出現了兩種狀況。一是已經填完了,結果出來了,而且它是合法的也就是它的解了;二是,找不到合法的值了,可是它卻仍是空着的,說明前面賦的值不對,此時再回去改,直到正確爲止。代碼以下:函數

check(u,i)函數是檢測在u(把宮格的格子編號,從左上角爲起始點一直到右下角,例如9宮格就有一、二、3...........80、81的編號)的位置,填入i合不合法

bool check(int u, int t)
{
    int x, y;
    x = (u - 1) / type + 1;
    y = (u - 1) % type + 1;//找到u這個位置的座標
    for (int i = 1; i <= type; i++)
    {
        if (gg[x][i] == t && i != y)    return false;
        if (gg[i][y] == t && i != x)   return false;

    }//判斷這個位置填入的數會不會與行和列衝突

    if (type == 4 || type == 6 || type == 8 || type == 9)
    {
        int xs, ys;
        int beginx, beginy;//當前座標所在宮格的左上角座標,可當作起始座標
        switch (type)//判斷宮格的規模
        {
        case 4:
            xs = 2;
            ys = 2;
            break;
        case 6:
            xs = 2;
            ys = 3;
            break;
        case 8:
            xs = 4;
            ys = 2;
            break;
        case 9:
            xs = 3;
            ys = 3;
            break;
        }
        int flogx = xs;
        int flogy = ys;//flogx和flogy只是待會下面用到的循環次數
        beginx = (x - 1) / xs * xs + 1;
        beginy = (y - 1) / ys * ys + 1;
        for (int i = beginx; flogx > 0; flogx--, i++)
        {

            for (int j = beginy; flogy > 0; flogy--, j++)
            {
                if (t == gg[i][j] && (x != i || y != j))    return false;
            }
            flogy = ys;
        }
        flogy = xs;
    }//判斷此位置填入的數會不會與宮格里的衝突

    return true;//能走到這裏說明填的數合法

}

上面的check函數會在dfs函數中用到,dfs的做用就是搜索

bool dfs(int u)
{
    if (u > type*type)  return true;//迭代到編號之外,說明前面填的數都是合法的
    int x, y;
    x = (u - 1) / type + 1;
    y = (u - 1) % type + 1;//給它座標化
    if (gg[x][y])   return dfs(u + 1);//若是這個位置有數字,就去下一個點
    else {
        for (int i = 1; i <= type; i++)
        {
            if (check(u, i))
            {

                gg[x][y] = i;
                if (dfs(u + 1))return true;
                gg[x][y] = 0;
            }
        }//這個位置還沒填入數據,就隨便給它一個值,而後再執行下一個點,若是下一個點不能夠了就會回來這個點從新賦值
        return false;
    }
}

測試結果


性能測試

相關文章
相關標籤/搜索