继上一篇博客之后,对数独解析方式进行了优化更新。

#include <stdio.h>
#include <stdlib.h>
#include <vector>
#include <string>
#include <map>

using namespace std;

void PrintVector(vector<vector<char> > &vvc)
{
    printf("---\n");
    for (vector<vector<char> >::iterator itor = vvc.begin();
        itor != vvc.end(); ++itor)
    {
        for (vector<char>::iterator vcItor = itor->begin();
            vcItor != itor->end(); ++vcItor)
        {
            printf("%c ", *vcItor);
        }
        printf("\n");
    }
}

#define MAX_LENGTH 9

class Solution {
public:
    void solveSudoku(vector<vector<char> >& board) {
        //统计每点未出现的数字,如果某数字在该列只出现在某一行,那么该数字必定只能出现在该位置
        vector<vector<char> > vvcTemp(board);
        map<int, string> misColRowExisted;//3*3 existed
        map<int, string> misDotReversed;
        for (int irow = 0; irow < MAX_LENGTH; ++irow)
        {
            for (int icol = 0; icol < MAX_LENGTH; ++icol)
            {
                misDotReversed[irow * MAX_LENGTH + icol] = "123456789";
            }
        }

        int rowIndex = 0;
        for (vector<vector<char> >::iterator itor = vvcTemp.begin(); itor != vvcTemp.end(); ++itor, ++rowIndex)
        {
            int colIndex = 0;
            for (vector<char>::iterator colItor = itor->begin(); colItor != itor->end(); ++colItor, ++colIndex)
            {
                if (*colItor != '.')
                {
                    misColRowExisted[rowIndex / 3 * 3 + colIndex / 3] += *colItor;
                }
            }
        }

        for (int row = 0; row < MAX_LENGTH; ++row)
        {
            for (int col = 0; col < MAX_LENGTH; ++col)
            {
                if (misDotReversed[row * MAX_LENGTH + col].length() > 1)
                {
                    for (int iLength = 0; iLength < misColRowExisted[row / 3 * 3 + col / 3].length(); ++iLength)
                    {
                        int iFindIndex = 0;
                        if ((iFindIndex =
                            misDotReversed[row * 9 + col].find(\
                                misColRowExisted[row / 3 * 3 + col / 3][iLength]))
                            != string::npos)
                        {
                            misDotReversed[row * 9 + col].erase(iFindIndex, 1);
                        }
                    }
                }

            }
        }

        int iRowIndex = 0;
        for (vector<vector<char> >::iterator itor = vvcTemp.begin(); itor != vvcTemp.end(); ++itor, ++iRowIndex)
        {
            int iColIndex = 0;
            for (vector<char>::iterator itor2 = itor->begin(); itor2 != itor->end(); ++itor2, ++iColIndex)
            {
                if (*itor2 != '.')
                {
                    for (int icol = 0; icol < MAX_LENGTH; ++icol)
                    {
                        //移除当前行所有包含该值的列的内容
                        int iPos = misDotReversed[iRowIndex * MAX_LENGTH + icol].find(*itor2);
                        if (iPos != string::npos)
                        {
                            misDotReversed[iRowIndex * MAX_LENGTH + icol].erase(iPos, 1);
                        }

                        //移除所有行在当前列包含该值的内容
                        iPos = misDotReversed[icol * MAX_LENGTH + iColIndex].find(*itor2);
                        if (iPos != string::npos)
                        {
                            misDotReversed[icol * MAX_LENGTH + iColIndex].erase(iPos, 1);
                        }
                    }

                    misDotReversed[iRowIndex * MAX_LENGTH + iColIndex] = *itor2;
                }
            }
        }

        bool bEnd = false;
        while (1)
        {
            if (bEnd)
            {
                break;
            }

            bEnd = true;

            iRowIndex = 0;
            for (vector<vector<char> >::iterator itor = vvcTemp.begin(); itor != vvcTemp.end(); ++itor, ++iRowIndex)
            {
                int iColIndex = 0;
                for (vector<char>::iterator itor2 = itor->begin(); itor2 != itor->end(); ++itor2, ++iColIndex)
                {
                    if (*itor2 == '.' && misDotReversed[iRowIndex * MAX_LENGTH + iColIndex].length() == 1)
                    {
                        bEnd = false;
                        *itor2 = misDotReversed[iRowIndex * MAX_LENGTH + iColIndex][0];

                        for (int j = 0; j < MAX_LENGTH; ++j)
                        {
                            int iPos = 0;
                            //从当前行的所有列当中包含该值的保留值内容中移除该值
                            if (misDotReversed[iRowIndex * MAX_LENGTH + j].length() > 1 &&
                                (iPos = misDotReversed[iRowIndex * MAX_LENGTH + j].find(*itor2)) != string::npos)
                            {
                                misDotReversed[iRowIndex * MAX_LENGTH + j].erase(iPos, 1);
                            }

                            //从当前列的所有行保留值当中包含该值的内容中移除该值
                            if (misDotReversed[j * MAX_LENGTH + iColIndex].length() > 1 &&
                                (iPos = misDotReversed[j * MAX_LENGTH + iColIndex].find(*itor2)) != string::npos)
                            {
                                misDotReversed[j * MAX_LENGTH + iColIndex].erase(iPos, 1);
                            }
                        }
                    }
                }
            }
        }

        map<int, vector<string> > misRowReversed;
        for (int temp = 0; temp < MAX_LENGTH; ++temp)
        {
            for (int jTemp = 0; jTemp < MAX_LENGTH; ++jTemp)
            {
                if (misDotReversed[temp * MAX_LENGTH + jTemp].length() > 1)
                {
                    misRowReversed[temp].push_back(misDotReversed[temp * MAX_LENGTH + jTemp]);
                }
            }
        }

        //从每格可能出现的值当中组成字符串,以此进行匹配
        //(12) (45)-> 14 15 24 25这种,而不是用排列组合进行匹配

        map<int, vector<string> > misRowInfo;
        misRowInfo.clear();
        for (int index = 0; index < 9; ++index)
        {
            vector<string> vstr;
            GenerateArray(misRowReversed[index], vstr);
            misRowInfo[index] = vstr;
        }

        //遍历数独的每行,并用misRowInfo的对应行去填充每行为'.'处,倘若填充之后为合法数独,则停止。
        //否则重新填充。
        vector<vector<char> > vvc(vvcTemp);
        vector<vector<char> > vvcTemp2;
        vvcTemp2.clear();
        //
        map<int, vector<string>::iterator> mItor;
        for (int i = 0; i < MAX_LENGTH; ++i)
        {
            mItor[i] = misRowInfo[i].begin();
        }
        vector<vector<char> >::iterator rowItor = vvc.begin();
        bool bNeedRecalc = false;
        vector<int> viNeedRecalcRowIndex;
        for (int rowIndex = 0; rowItor != vvc.end();)
        {
            if (!misRowInfo[rowIndex].empty() && mItor[rowIndex] == misRowInfo[rowIndex].end())
            {
                if (0 == rowIndex)
                {
                    return;
                }

                mItor[rowIndex] = misRowInfo[rowIndex].begin();
                vvcTemp2.pop_back();
                --rowItor;
                --rowIndex;
                continue;
            }
            vector<char> vctemp;
            int colIndex = 0;
            for (vector<char>::iterator colItor = rowItor->begin(); colItor != rowItor->end(); ++colItor)
            {
                if ((*colItor) == '.')
                {
                    vctemp.push_back((*(mItor[rowIndex]))[colIndex]);
                    ++colIndex;
                }
                else
                {
                    vctemp.push_back(*colItor);
                }
            }
            vvcTemp2.push_back(vctemp);
            if (!isValidSudoku(vvcTemp2))
            {
                vvcTemp2.pop_back();
                //如果当前行的所有值全都确定,那么misRowInfo[rowIndex]必定是空的,所以如果数独非法,必定是该行的上一行有问题
                if (misRowInfo[rowIndex].empty())
                {
                    for (int i = rowIndex; i >= 0; --i)
                    {
                        if (misRowInfo[i].empty())
                        {
                            vvcTemp2.pop_back();
                            if (rowItor != vvc.begin())
                            {
                                --rowIndex;
                                --rowItor;
                            }
                            continue;
                        }
                        else
                        {
                            if (mItor[i] != misRowInfo[i].end())
                                ++mItor[i];
                            if (mItor[i] == misRowInfo[i].end())
                            {
                                if (0 == rowIndex)
                                    return;
                                for (int j = rowIndex; j >= 0; --j)
                                {
                                    mItor[j] = misRowInfo[j].begin();
                                    vvcTemp2.pop_back();
                                    --rowItor;
                                    --rowIndex;
                                }
                            }
                            break;
                        }
                    }
                    continue;
                }
                if (mItor[rowIndex] != misRowInfo[rowIndex].end())
                    ++mItor[rowIndex];
                if (mItor[rowIndex] == misRowInfo[rowIndex].end())
                {
                    if (0 == rowIndex)
                    {
                        return;
                    }

                    for (int i = rowIndex; i < MAX_LENGTH; ++i)
                    {
                        mItor[i] = misRowInfo[i].begin();
                    }
                    vvcTemp2.pop_back();
                    --rowIndex;
                    --rowItor;
                }
                continue;
            }
            //PrintVector(vvcTemp2);
            if (!misRowInfo[rowIndex].empty())
            {
                ++mItor[rowIndex];
                if (mItor[rowIndex] == misRowInfo[rowIndex].end())
                {
                    bool bContinue = false;
                    vector<int>::iterator reCalcItor = viNeedRecalcRowIndex.end();
                    if (!viNeedRecalcRowIndex.empty())
                    {
                        --reCalcItor;
                        if (*reCalcItor == rowIndex)
                        {
                            viNeedRecalcRowIndex.erase(reCalcItor);
                            if (!vvcTemp2.empty())
                                vvcTemp2.pop_back();
                            if (!vvcTemp2.empty())
                                vvcTemp2.pop_back();
                            if (rowItor != vvc.begin())
                            {
                                --rowItor;
                                --rowIndex;
                            }
                            bContinue = true;
                        }
                    }

                    if (bContinue)
                        continue;

                    viNeedRecalcRowIndex.push_back(rowIndex);
                    for (int i = rowIndex + 1; i < MAX_LENGTH; ++i)
                    {
                        mItor[i] = misRowInfo[i].begin();
                    }

                    --mItor[rowIndex];
                }
            }
            ++rowItor;
            ++rowIndex;
        }

        board = vvcTemp2;
    }

    void GenerateArray(vector<string > &vStr, vector<string> &vResult)
    {
        for (vector<string>::iterator itor = vStr.begin();
            itor != vStr.end(); ++itor)
        {
            if (vResult.empty())
            {
                for (int iLength = 0; iLength < (*itor).length(); ++iLength)
                {
                    string s = "";
                    s += (*itor)[iLength];
                    vResult.push_back(s);
                }
            }
            else
            {
                vector<string> vTemp;
                vTemp.clear();
                for (vector<string>::iterator resItor = vResult.begin();
                    resItor != vResult.end(); ++resItor)
                {
                    for (int iLength = 0; iLength < (*itor).length(); ++iLength)
                    {
                        if ((*resItor).find((*itor)[iLength]) == string::npos)
                            vTemp.push_back(*resItor + (*itor)[iLength]);
                    }
                }

                vResult.clear();
                vResult = vTemp;
            }
        }
    }

    bool isValidSudoku(vector<vector<char> >& vvc)
    {
        vector<vector<char> >::iterator vvItor = vvc.begin();
        //如果一行当中出现两个相同的数字,肯定是不合法的数独
        //如果一列当中出现两个相同的数字,也肯定是不合法的数独
        map<int, string> mColInfo;
        map<int, string> mRowInfo;
        //每9个小格数字统计,9个小格数字也不能有重复
        map<int, string> mColRowInfo;
        map<int, int> mRowReversed;
        map<int, int> mColReversed;
        for (int index = 0; index < 9; ++index)
        {
            mRowReversed[index] = 0;
            mColReversed[index] = 0;
        }

        for (int i = 0; vvItor != vvc.end(); ++vvItor, ++i)
        {
            vector<char>::iterator vItor = vvItor->begin();
            string sRow = "";
            for (int k = 0; vItor != vvItor->end(); ++vItor, ++k)
            {
                if (*vItor != '.')
                {
                    if (sRow.find(*vItor) != string::npos)
                        return false;
                    else
                        sRow += *vItor;

                    if (mColInfo[k].find(*vItor) != string::npos)
                        return false;
                    else
                        mColInfo[k] += *vItor;

                    //81个数字共分为9个小格,小格的编号计算方式 列号/3+行号/3*3
                    //int j = k/3 + i/3*3;
                    if (mColRowInfo[k/3 + i/3*3].find(*vItor) != string::npos)
                        return false;
                    else
                        mColRowInfo[k/3 + i/3*3] += *vItor;
                }

                if (*vItor == '.')
                {
                    mRowReversed[i] += 1;
                    mColReversed[k] += 1;
                }
            }
            mRowInfo[i] = sRow;
        }

        return true;
    }
};

int main(int argc, char **argv)
{
    vector<string> vStr;

    //入门数独  0m0.023s
    vStr.push_back("..5..1627");
    vStr.push_back(".6.347158");
    vStr.push_back("71.6.2.93");
    vStr.push_back("..3218746");
    vStr.push_back(".7.439582");
    vStr.push_back("8245..9.1");
    vStr.push_back("4891...75");
    vStr.push_back("231795864");
    vStr.push_back(".578243..");

    //初级  115m16.032s
    //vStr.push_back("....6.3..");
    //vStr.push_back(".74.....8");
    //vStr.push_back("..2......");
    //vStr.push_back("..9....4.");
    //vStr.push_back("2...5....");
    //vStr.push_back("....3....");
    //vStr.push_back("3.18.....");
    //vStr.push_back("...4...2.");
    //vStr.push_back("......5..");

    //0m43.788s  ->  0m2.590s
    //vStr.push_back("..421.8.3");
    //vStr.push_back("..6......");
    //vStr.push_back(".7.9.....");
    //vStr.push_back(".........");
    //vStr.push_back("1.2.435..");
    //vStr.push_back("...6.79..");
    //vStr.push_back(".......4.");
    //vStr.push_back(".35.....9");
    //vStr.push_back("....3.1.8");

    //*********************
    //蓝天5级 高级 0m30.763s  ->  0m0.795s
    //vStr.push_back(".........");
    //vStr.push_back(".94.3..1.");
    //vStr.push_back("...2.9.5.");
    //vStr.push_back("..89.32..");
    //vStr.push_back(".3..7..9.");
    //vStr.push_back("..71.58..");
    //vStr.push_back(".6.8.4...");
    //vStr.push_back(".7..6.98.");
    //vStr.push_back(".........");

    //蓝天6级 超高级 0m29.257s  ->  0m2.254s
    //vStr.push_back("...3..2..");
    //vStr.push_back(".2....5.3");
    //vStr.push_back("..45..1.7");
    //vStr.push_back(".5..13...");
    //vStr.push_back("....4....");
    //vStr.push_back("...78..3.");
    //vStr.push_back("4.5..68..");
    //vStr.push_back("2.8....6.");
    //vStr.push_back("..7..2...");

    //0m6.672s  ->  0m0.281s
     //vStr.push_back(".3....96.");
     //vStr.push_back("1....6..3");
     //vStr.push_back("4..1.....");
     //vStr.push_back(".1..3.7..");
     //vStr.push_back("...5.4...");
     //vStr.push_back("..8.7..2.");
     //vStr.push_back(".....2..6");
     //vStr.push_back("9..8....2");
     //vStr.push_back(".82....5.");

     //vStr.push_back("53..7....");
     //vStr.push_back("6..195...");
     //vStr.push_back(".98....6.");
     //vStr.push_back("8...6...3");
     //vStr.push_back("4..8.3..1");
     //vStr.push_back("7...2...6");
     //vStr.push_back(".6....28.");
     //vStr.push_back("...419..5");
     //vStr.push_back("....8..79");
     //6m25.284s ->  0m0.024s

    //0m18.263s  ->  0m1.999s
    //vStr.push_back(".........");
    //vStr.push_back(".63...95.");
    //vStr.push_back(".8.13..2.");
    //vStr.push_back("...6.27..");
    //vStr.push_back("..5.7.6..");
    //vStr.push_back("..73.4...");
    //vStr.push_back(".5..89.3.");
    //vStr.push_back(".12...89.");
    //vStr.push_back(".........");

    vector<vector<char> > vvChar;
    vector<char> vChar;
    for (vector<string>::iterator itor = vStr.begin(); itor != vStr.end(); ++itor)
    {
        vChar.clear();
        for (size_t index = 0; index < (*itor).length(); ++index)
        {
            vChar.push_back((*itor)[index]);
        }
        vvChar.push_back(vChar);
    }

    for (vector<vector<char> >::iterator itor = vvChar.begin(); itor != vvChar.end(); ++itor)
    {
        vector<char>::iterator itor2 = itor->begin();
        for (; itor2 != itor->end(); ++itor2)
        {
            printf("%c ", *itor2);
        }
        printf("\n");
    }

    Solution sl;
    sl.solveSudoku(vvChar);

    printf("========================================\n");

    for (vector<vector<char> >::iterator itor = vvChar.begin(); itor != vvChar.end(); ++itor)
    {
        vector<char>::iterator itor2 = itor->begin();
        for (; itor2 != itor->end(); ++itor2)
        {
            printf("%c ", *itor2);
        }
        printf("\n");
    }

    return 0;
}

猜你喜欢

转载自blog.csdn.net/u011803182/article/details/75240552