首页 » 编程之美 » 正文

[leetcode_37]Sudoku Solver

数独解法,哈哈,之前有个折磨了好久的题,我写过该解法,拿来改了改即可。
首先,网上有论文支持当已知点的个数小于17是无解的。
然后,暴力即可,暴力的技巧是:从可能性少的开始搜索。

struct Pointxy {
    int x;
    int y;
    int val;
};
int cmp(Pointxy a,Pointxy b) {
    return a.val < b.val;
}
class Solution {
public:
    int bitarray[9];
    int map[9][9];
    bool result;
    int CountOnes(int v)
    {
        int number = 0;
        while(v)
        {
            v &= (v-1);
            number++;
        }
        return number;
    }
    int GetRegionOfBoard(int x,int y) {
        if(x>= 0 && x < 3) {
            if(y >= 0 && y < 3)return 0;
            if(y >= 3 && y < 6)return 1;
            if(y >= 6 && y < 9)return 2;
        }
        if(x >= 3 && x < 6) {
            if(y >= 0 && y < 3)return 3;
            if(y >= 3 && y < 6)return 4;
            if(y &gt;= 6 &amp;&amp; y &lt; 9)return 5;<br />
        }
        if(x &gt;= 6 &amp;&amp; x &lt; 9) {
            if(y &gt;= 0 &amp;&amp; y &lt; 3)return 6;
            if(y &gt;= 3 &amp;&amp; y &lt; 6)return 7;
            if(y &gt;= 6 &amp;&amp; y &lt; 9)return 8;
        }
    }
    bool RefeshMap(int x,int y){
        int set_tmp = 0;
        for(int i = 0;i &lt; 9;i++) {
            if(CountOnes(map[x][i]) == 1) {
                set_tmp = set_tmp | map[x][i];
            }
            if(CountOnes(map[i][y]) == 1) {
                set_tmp = set_tmp | map[i][y];<br />
            }
        }
        int region = GetRegionOfBoard(x,y);
        int x_r = (region / 3 + 1)<em>3;
        int y_r = (region % 3 + 1)</em>3;
        for(int i = x_r-3;i &lt; x_r;i++) {
            for(int j = y_r-3;j &lt; y_r;j++) {
                if(CountOnes(map[i][j]) == 1) {
                    set_tmp = set_tmp | map[i][j];<br />
                }
            }
        }
        if(set_tmp == 511)return false;
        map[x][y] = 511 - set_tmp;
        return true;
    }
    void Move(Pointxy pxy[81],int index,vector&lt;vector&lt;char&gt; &gt; &amp;board) {
        if(result == true)return;
        if(index &lt;= 0) {
            result = true;
            /<em>for(int i = 0;i &lt; 9;i++) {
                for(int j = 0;j &lt; 9;j++) {
                    printf(&quot;%c&quot;,board[i][j]);
                }
                printf(&quot;\n&quot;);
            }</em>/
            return;
        }
        else {
            sort(pxy,pxy+index,cmp);
            int pi = pxy[0].x;
            int pj = pxy[0].y;
            for(int ibit = 0;ibit &lt; 9;ibit++) {
                if(result == true)return;
                if(map[pi][pj] &amp; bitarray[ibit]) {
                    if(pi == 0&amp;&amp;pj == 6) {
                        int hujiulin = 1;
                    }
                    board[pi][pj] = ibit+1+'0';
                    map[pi][pj] -= bitarray[ibit];
                    int xtmp[81];
                    int ytmp[81];
                    int indextmp = 0;
                    for(int i = 1;i &lt; index;i++) {
                        int xi = pxy[i].x;
                        int yi = pxy[i].y;
                        if(xi == pi || yi == pj || GetRegionOfBoard(xi,yi) == GetRegionOfBoard(pi,pj)) {
                            if(map[xi][yi] &amp; bitarray[ibit]) {
                                xtmp[indextmp] = xi;
                                ytmp[indextmp++] = yi;
                                map[xi][yi] -= bitarray[ibit];
                            }
                        }
                    }
                    Pointxy pxyt[81];
                    int indext = 0;
                    for(int i = 1;i &lt; index;i++) {
                        pxyt[indext].x = pxy[i].x;
                        pxyt[indext].y = pxy[i].y;
                        pxyt[indext].val = CountOnes(map[pxyt[indext].x][pxyt[indext].y]);
                        indext++;
                    }
                    Move(pxyt,indext,board);
                    for(int i = 0;i &lt; indextmp;i++) {
                        int xi = xtmp[i];
                        int yi = ytmp[i];
                        map[xi][yi] += bitarray[ibit];
                    }
                    map[pi][pj] += bitarray[ibit];
                    //board[pi][pj] = '.';
                }
            }
        }
    }
    void solveSudoku(vector&lt;vector&lt;char&gt; &gt; &amp;board) {
        for(int i = 0;i &lt; 9;i++) {
            bitarray[i] = (int)pow(2.0,i);
        }
        int count = 0;
        for(int i = 0;i &lt; 9;i++) {
            for(int j = 0;j &lt; 9;j++) {
                if(board[i][j] == '.') {
                    map[i][j] = 511;
                }
                else {
                    map[i][j] = bitarray[board[i][j] - '0'-1];
                    count++;
                }
            }
        }
        if(count &lt; 17)return ;
        Pointxy pxy[81];
        int index = 0;
        for(int i = 0;i &lt; 9;i++) {
            for(int j = 0;j &lt; 9;j++) {
                if(map[i][j] == 511) {
                    if(RefeshMap(i,j) == false)return ;
                    pxy[index].x = i;
                    pxy[index].y = j;
                    pxy[index++].val = CountOnes(map[i][j]);
                }
                if(CountOnes(map[i][j]) == 1) {
                    int k = 0;
                    for(k = 0;k &lt; 9;k++) {
                        if(map[i][j] == bitarray[k])break;
                    }
                    board[i][j] = k+1+'0';
                }
            }
        }
        result = false;
        Move(pxy,index,board);
        //return result;</p>

<pre><code>}
</code></pre>

<p>};

发表评论