c++实现的简单数独策画器

    添加时间:2013-5-30 点击量:

    日常平凡挺喜好写小法度的,然则不知道写啥,无意看到关于数独的消息,感觉用小法度实现再合适不过了,网上一搜,有道理,有法度,然则没有找到优良的代码,干脆本身写了一个,固然也不优良,起码本身看得懂。


    道理:


    1、每个格子可所以1-9的数,n行m列的数断定后,则第n行,第m列,nm地点的”宫“里其他的格子就不克不及是这个数了。


    2、刚开端每个格子都有9个”候选数“,慢慢把初始数据添加到终极的格子中,并把响应的格子中的候选数更新,如1所说。


    3、开端策画,选出候选数起码的格子,对这些数迭代测试,如把候选数中的第1个添加到终极的格子中。和2一样更新其他格子的候选数列表。


    4、3之后天然还是3,所以把3实现为递归要简单一些。并且推敲到本题实际景象最多递归81层,不会栈溢出。并且递归本身还保存了后续所需数据,简化了操纵。


    代码注释:


    g_currentIndex:格子中已经断定成果的个数(添加到格子中的数的个数,递归的深度),索引默示的,所以0代表已添加1个。


    g_affectedFlags:位标记,某次添加数据是否对格子产生影响,回退操纵要应用。


    g_candidate:每个格子的候选列表,用bitset的索引默示。第n位为1,代表n是候选数。


    g_candidateNum:每个格子的候选个数,为什么不消bitset的count呢?因为速度太慢。


    成果截图:



    源码:



    #include<iostream>
    
    #include
    <set>
    #include
    <bitset>
    #include
    <cstring>
    #include
    <time.h>

    using namespace std;

    int g_currentIndex=-1;
    bitset
    <81> g_affectedFlags[9][9];
    bitset
    <10> g_candidate[9][9];
    int g_candidateNum[9][9];
    int resultNum;
    const int maxNum=5;

    int g_map[9][9]={
    {
    800000000},
    {
    003600000},
    {
    070090200},
    {
    050007000},
    {
    000045700},
    {
    000100030},
    {
    001000068},
    {
    008500010},
    {
    090000400},
    };

    void AddElement(int row,int column,int num)
    {
    ++g_currentIndex;
    g_map[row][column]
    =num;

    int old;
    forint i=0;i<9;++i)
    {
    if(g_map[row][i]==0 && g_candidate[row][i].test(num))
    {
    g_candidate[row][i].reset(num);
    --g_candidateNum[row][i];
    g_affectedFlags[row][i].
    set(g_currentIndex);
    }

    if(g_map[i][column]==0 && g_candidate[i][column].test(num))
    {
    g_candidate[i][column].reset(num);
    --g_candidateNum[i][column];
    g_affectedFlags[i][column].
    set(g_currentIndex);
    }
    }

    int palaceRow=row>2?(row>56:3):0;
    int palaceColumn=column>2?(column>56:3):0;

    forint i=0;i<3;++i)
    {
    forint j=0;j<3;++j)
    {
    row
    =palaceRow+i;
    column
    =palaceColumn+j;
    if(g_map[row][column]==0 && g_candidate[row][column].test(num))
    {
    g_candidate[row][column].reset(num);
    --g_candidateNum[row][column];
    g_affectedFlags[row][column].
    set(g_currentIndex);
    }
    }
    }
    }

    void RecoverElement(int row,int column,int num)
    {
    g_map[row][column]
    =0;
    forint i=0;i<9;++i)
    {
    if(g_map[row][i]==0 && g_affectedFlags[row][i].test(g_currentIndex))
    {
    g_candidate[row][i].
    set(num);
    ++g_candidateNum[row][i];
    g_affectedFlags[row][i].reset(g_currentIndex);
    }

    if(g_map[i][column]==0 && g_affectedFlags[i][column].test(g_currentIndex))
    {
    g_candidate[i][column].
    set(num);
    ++g_candidateNum[i][column];
    g_affectedFlags[i][column].reset(g_currentIndex);
    }
    }

    int palaceRow=row>2?(row>56:3):0;
    int palaceColumn=column>2?(column>56:3):0;

    forint i=0;i<3;++i)
    {
    forint j=0;j<3;++j)
    {
    row
    =palaceRow+i;
    column
    =palaceColumn+j;
    if(g_map[row][column]==0 && g_affectedFlags[row][column].test(g_currentIndex))
    {
    g_candidate[row][column].
    set(num);
    ++g_candidateNum[row][column];
    g_affectedFlags[row][column].reset(g_currentIndex);
    }
    }
    }

    --g_currentIndex;
    }

    void Init()
    {
    forint i=0;i<9;++i)
    {
    forint j=0;j<9;++j)
    {
    g_candidate[i][j].
    set();
    g_candidateNum[i][j]
    =10;
    }
    }

    forint i=0;i<9;++i)
    {
    forint j=0;j<9;++j)
    {
    if(g_map[i][j]!=0
    AddElement(i,j,g_map[i][j]);
    }
    }
    }

    bool FindBest(int &row,int &column)
    {
    int min=999;
    forint i=0;i<9;++i)
    {
    forint j=0;j<9;++j)
    {
    if(g_map[i][j]==0 && g_candidateNum[i][j]>1 && g_candidateNum[i][j]<min)
    {
    row
    =i;
    column
    =j;
    min
    =g_candidateNum[i][j];
    }
    }
    }

    if(min==999
    return false;
    return true;
    }

    bool CheckResult()
    {
    set<int> elements;
    set<int> elements2;

    forint i=0;i<9;++i)
    {
    forint j=0;j<9;++j)
    {
    elements.(g_map[i][j]);
    elements2.(g_map[j][i]);
    }
    if(elements.size()!=9
    return false;
    if(elements2.size()!=9
    return false;
    elements.clear();
    elements2.clear();
    }

    elements.clear();
    int row,column;
    forint i=0;i<3;++i)
    {
    forint j=0;j<3;++j)
    {
    row
    =i3;
    column
    =j3;
    forint k=0;k<9;++k)
    {
    elements.(g_map[row
    +k/3][column+k%3]);
    }
    if(elements.size()!=9
    return false;

    elements.clear();
    }
    }
    return true;
    }

    void OutputResult()
    {
    cout
    <<endl;
    forint i=0;i<9;++i)
    {
    forint j=0;j<9;++j)
    {
    cout
    <<g_map[i][j]<< ;
    }
    cout
    <<endl;
    }
    }

    bool Try()
    {
    int row,column;
    if(!FindBest(row,column))
    return true;

    forint i=1;i<10;++i)
    {
    if(!g_candidate[row][column].test(i))
    continue;

    AddElement(row,column,i);

    if(Try())
    {
    if(g_currentIndex==80 && CheckResult())
    {
    cout
    <<endl<<Result:<<++resultNum<<endl;
    OutputResult();

    if(resultNum>=maxNum)
    return false;

    }
    }
    else
    return false;

    RecoverElement(row,column,i);
    }

    return true;
    }

    int main()
    {
    double start,end,cost;
    start
    =clock();

    Init();
    Try();

    if(resultNum)
    cout
    <<endl<<OK!<<endl;
    else
    cout
    <<endl<<Wrong Input!<<endl;

    end
    =clock();
    cost
    =end-start;
    cout
    <<Costed time:<<cost<<ms<<endl;

    char c;
    cin
    >>c;

    return 0;
    }


    其他:


    小我感觉这种办法已经到了速度的极限,高手的代码竟然可以或许达到几十毫秒,默示自叹不如!


    我用的例子是”史上最难数独“,确切只有一个解,代码中maxNum可以限制显示成果数量。


    附其他高手的截图一张:


    我们永远不要期待别人的拯救,只有自己才能升华自己。自己已准备好了多少容量,方能吸引对等的人与我们相遇,否则再美好的人出现、再动人的事情降临身边,我们也没有能量去理解与珍惜,终将擦肩而过。—— 姚谦《品味》
    分享到: