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

来源:互联网 发布:单片机各引脚功能 编辑:程序博客网 时间:2024/06/05 19:05
#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 9class 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;}

阅读全文
0 0