用c++写的效率低下的数独解析

最近在刷leetcode,发现好多问题还挺有意思的。但是碰到问题,找不到更优的解决方法,按照自己的想法搞出来的方式效率有点低,碰到较为复杂的数独就会严重超时导致没有结果能出来。

先在这里写一个,后续优化之后再放出来。


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

#ifdef WIN32
#include <Windows.h>
#else
#include <unistd.h>//getcwd
#include <string.h>//memset
#endif

using namespace std;

class Solution {
public:
    void solveSudoku(vector<vector<char> >& board) {
        //2统计每行未出现的值
        //3统计每格未出现的数字,如果某数字在该列只出现在某一行,那么该数字必定只能出现在该位置
        map<int, string> misColRowReversed;//每格可能出现的值汇总
        for (int index = 0; index < 9; ++index)
        {
            for (int j = 0; j < 9; ++j)
            {
                misColRowReversed[index * 9 + j] = "123456789";
            }
        }

        vector<vector<char> >::iterator vvcItor = board.begin();
        for (int rowIndex = 0; vvcItor != board.end(); ++vvcItor, ++rowIndex)
        {
            vector<char>::iterator vcItor = vvcItor->begin();
            for (int k = 0; vcItor != vvcItor->end(); ++vcItor, ++k)
            {
                if (*vcItor != '.')
                {
                    for (int j = 0; j < 9; ++j)
                    {
                        //将已经出现的数字从每格保留值当中移除
                        int iFindIndex = 0;
                        iFindIndex = misColRowReversed[rowIndex * 9 + j].find(*vcItor);
                        if (iFindIndex != string::npos)
                        {
                            misColRowReversed[rowIndex * 9 + j].erase(iFindIndex, 1);
                        }

                        iFindIndex = misColRowReversed[j * 9 + k].find(*vcItor);
                        if (iFindIndex != string::npos)
                        {
                            misColRowReversed[j * 9 + k].erase(iFindIndex, 1);
                        }
                    }

                    misColRowReversed[rowIndex * 9 + k] = "";
                    misColRowReversed[rowIndex * 9 + k] += *vcItor;
                }
            }
        }

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

            bOver = true;
            int rowIndex4 = 0;
            for (vvcItor = board.begin(); vvcItor != board.end(); ++vvcItor, ++rowIndex4)
            {
                map<int, string> misColSum;
                misColSum.clear();

                //如果一行当中,某个值在一个位置出现,那么这个值只能出现在该位置。与此同时,当前行和列种应移除该值。
                vector<char>::iterator itor = vvcItor->begin();
                for (int jColIndex = 0; itor != vvcItor->end(); ++itor, ++jColIndex)
                {
                    //汇总每列所有可能出现的值
                    string colStr = "";
                    for (int kRowIndex = 0; kRowIndex < 9; ++kRowIndex)
                    {
                        if (misColRowReversed[kRowIndex * 9 + jColIndex].length() > 1)
                        {
                            colStr += misColRowReversed[kRowIndex * 9 + jColIndex];
                        }
                    }
                    map<char, int> mci;
                    mci.clear();
                    for (int i = 0; i < 9; ++i)
                    {
                        mci['1' + i] = 0;
                    }

                    for (int i = 0; i < colStr.length(); ++i)
                    {
                        mci[colStr[i]]++;
                    }

                    char ch;
                    for (map<char, int>::iterator mciItor = mci.begin(); mciItor != mci.end(); ++mciItor)
                    {
                        //某值只可能出现一次,那么这个值就只能出现在该位置
                        if (mciItor->second == 1)
                        {
                            ch = mciItor->first;
                            for (int kRowIndex = 0; kRowIndex < 9; ++kRowIndex)
                            {
                                int iPos = 0;
                                if (misColRowReversed[kRowIndex * 9 + jColIndex].length() > 1 &&
                                    (iPos = misColRowReversed[kRowIndex * 9 + jColIndex].find(ch)) != string::npos)
                                {
                                    misColRowReversed[kRowIndex * 9 + jColIndex] = "";
                                    misColRowReversed[kRowIndex * 9 + jColIndex] += ch;

                                    //当前行 kRowIndex 的所有列应该移除包含ch的内容
                                    for (int lColIndex = 0; lColIndex < 9; ++lColIndex)
                                    {
                                        if (misColRowReversed[kRowIndex * 9 + lColIndex].length() > 1 &&
                                            (iPos = misColRowReversed[kRowIndex * 9 + lColIndex].find(ch)) != string::npos)
                                        {
                                            misColRowReversed[kRowIndex * 9 + lColIndex].erase(iPos, 1);
                                        }
                                    }
                                }
                            }
                        }
                    }

                    //如果一个点没值,而这个点可能出现的值只有一个,那么该值肯定只能在该位置。
                    //这个值写入之后,对应行和列的保留值当中,需要移除该值。
                    if (*itor == '.' && misColRowReversed[rowIndex4 * 9 + jColIndex].length() == 1)
                    {
                        bOver = false;
                        *itor = misColRowReversed[rowIndex4 * 9 + jColIndex][0];

                        for (int i = 0; i < 9; ++i)
                        {
                            if (misColRowReversed[i * 9 + jColIndex].length() > 1)
                            {
                                int iIndex = misColRowReversed[i * 9 + jColIndex].find(*itor);
                                if (iIndex != string::npos)
                                {
                                    misColRowReversed[i * 9 + jColIndex].erase(iIndex, 1);
                                }
                            }
                        }
                    }
                }
            }
        }

        //计算出每行可能出现哪些填充排列
        map<int, vector<string> > mivsRow;//保存每一行可能出现的排列组合都有哪些
        mivsRow.clear();
        for (int row = 0; row < 9; ++row)
        {
            vector<string> vstr;
            vstr.clear();

            vector<string> vstrValidNums;
            vstrValidNums.clear();
            for (int iCol = 0; iCol < 9; ++iCol)
            {
                if (misColRowReversed[row * 9 + iCol].length() > 1)
                {
                    vstrValidNums.push_back(misColRowReversed[row * 9 + iCol]);
                }
            }

            GenerateArray(vstrValidNums, vstr);
            mivsRow[row] = vstr;
        }

        //遍历数独的每行,并用mivsRow的对应行去填充每行为'.'处,倘若填充之后为合法数独,则停止。
        //否则重新填充。
        vector<string>::iterator row1Itor;
        vector<string>::iterator row2Itor;
        vector<string>::iterator row3Itor;
        vector<string>::iterator row4Itor;
        vector<string>::iterator row5Itor;
        vector<string>::iterator row6Itor;
        vector<string>::iterator row7Itor;
        vector<string>::iterator row8Itor;
        vector<string>::iterator row9Itor;

        vector<vector<char> > vvc(board);
        vector<vector<char> > vvcTemp;
        vvcTemp.clear();
        for (row1Itor = mivsRow[0].begin(); row1Itor != mivsRow[0].end(); ++row1Itor)
        {
            vector<vector<char> >::iterator rowItor = vvc.begin();
            int row1ColIndex = 0;
            vector<char> vcTemp;
            for (vector<char>::iterator itor1 = (*rowItor).begin(); itor1 != (*rowItor).end(); ++itor1)
            {
                if (*itor1 == '.')
                {
                    vcTemp.push_back((*row1Itor)[row1ColIndex]);
                    ++row1ColIndex;
                }
                else
                {
                    vcTemp.push_back(*itor1);
                }
            }

            vvcTemp.push_back(vcTemp);
            if (!isValidSudoku(vvcTemp))
            {
                vvcTemp.pop_back();
                continue;
            }

            ++rowItor;

            for (row2Itor = mivsRow[1].begin();
                row2Itor != mivsRow[1].end(); ++row2Itor)
            {
                int row2ColIndex = 0;
                vcTemp.clear();
                for (vector<char>::iterator itor2 = (*rowItor).begin();
                    itor2 != (*rowItor).end(); ++itor2)
                {
                    if (*itor2 == '.')
                    {
                        vcTemp.push_back((*row2Itor)[row2ColIndex]);
                        ++row2ColIndex;
                    }
                    else
                    {
                        vcTemp.push_back(*itor2);
                    }
                }

                vvcTemp.push_back(vcTemp);
                if (!isValidSudoku(vvcTemp))
                {
                    vvcTemp.pop_back();
                    continue;
                }
                ++rowItor;

                for (row3Itor = mivsRow[2].begin();
                    row3Itor != mivsRow[2].end(); ++row3Itor)
                {
                    int row3ColIndex = 0;
                    vcTemp.clear();
                    for (vector<char>::iterator itor3 = (*rowItor).begin();
                        itor3 != (*rowItor).end(); ++itor3)
                    {
                        if (*itor3 == '.')
                        {
                            vcTemp.push_back((*row3Itor)[row3ColIndex]);
                            ++row3ColIndex;
                        }
                        else
                        {
                            vcTemp.push_back(*itor3);
                        }
                    }

                    vvcTemp.push_back(vcTemp);
                    if (!isValidSudoku(vvcTemp))
                    {
                        vvcTemp.pop_back();
                        continue;
                    }
                    ++rowItor;

                    for (row4Itor = mivsRow[3].begin(); row4Itor != mivsRow[3].end(); ++row4Itor)
                    {
                        int row4ColIndex = 0;
                        vcTemp.clear();
                        for (vector<char>::iterator itor4 = (*rowItor).begin();
                            itor4 != (*rowItor).end(); ++itor4)
                        {
                            if (*itor4 == '.')
                            {
                                vcTemp.push_back((*row4Itor)[row4ColIndex]);
                                ++row4ColIndex;
                            }
                            else
                            {
                                vcTemp.push_back(*itor4);
                            }
                        }
                        vvcTemp.push_back(vcTemp);
                        if (!isValidSudoku(vvcTemp))
                        {
                            vvcTemp.pop_back();
                            continue;
                        }
                        ++rowItor;

                        for (row5Itor = mivsRow[4].begin(); row5Itor != mivsRow[4].end(); ++row5Itor)
                        {
                            int row5ColIndex = 0;
                            vcTemp.clear();
                            for (vector<char>::iterator itor5 = (*rowItor).begin();
                                itor5 != (*rowItor).end(); ++itor5)
                            {
                                if (*itor5 == '.')
                                {
                                    vcTemp.push_back((*row5Itor)[row5ColIndex]);
                                    ++row5ColIndex;
                                }
                                else
                                {
                                    vcTemp.push_back(*itor5);
                                }
                            }

                            vvcTemp.push_back(vcTemp);
                            if (!isValidSudoku(vvcTemp))
                            {
                                vvcTemp.pop_back();
                                continue;
                            }
                            ++rowItor;

                            for (row6Itor = mivsRow[5].begin(); row6Itor != mivsRow[5].end(); ++row6Itor)
                            {
                                int row6ColIndex = 0;
                                vcTemp.clear();
                                for (vector<char>::iterator itor6 = (*rowItor).begin();
                                    itor6 != (*rowItor).end(); ++itor6)
                                {
                                    if (*itor6 == '.')
                                    {
                                        vcTemp.push_back((*row6Itor)[row6ColIndex]);
                                        ++row6ColIndex;
                                    }
                                    else
                                    {
                                        vcTemp.push_back(*itor6);
                                    }
                                }

                                vvcTemp.push_back(vcTemp);
                                if (!isValidSudoku(vvcTemp))
                                {
                                    vvcTemp.pop_back();
                                    continue;
                                }

                                ++rowItor;

                                for (row7Itor = mivsRow[6].begin(); row7Itor != mivsRow[6].end(); ++row7Itor)
                                {
                                    int row7ColIndex = 0;
                                    vcTemp.clear();
                                    for (vector<char>::iterator itor7 = (*rowItor).begin();
                                        itor7 != (*rowItor).end(); ++itor7)
                                    {
                                        if (*itor7 == '.')
                                        {
                                            vcTemp.push_back((*row7Itor)[row7ColIndex]);
                                            ++row7ColIndex;
                                        }
                                        else
                                        {
                                            vcTemp.push_back(*itor7);
                                        }
                                    }

                                    vvcTemp.push_back(vcTemp);
                                    if (!isValidSudoku(vvcTemp))
                                    {
                                        vvcTemp.pop_back();
                                        continue;
                                    }

                                    ++rowItor;

                                    for (row8Itor = mivsRow[7].begin(); row8Itor != mivsRow[7].end(); ++row8Itor)
                                    {
                                        int row8ColIndex = 0;
                                        vcTemp.clear();
                                        for (vector<char>::iterator itor8 = (*rowItor).begin();
                                            itor8 != (*rowItor).end(); ++itor8)
                                        {
                                            if (*itor8 == '.')
                                            {
                                                vcTemp.push_back((*row8Itor)[row8ColIndex]);
                                                ++row8ColIndex;
                                            }
                                            else
                                            {
                                                vcTemp.push_back(*itor8);
                                            }
                                        }

                                        vvcTemp.push_back(vcTemp);
                                        if (!isValidSudoku(vvcTemp))
                                        {
                                            vvcTemp.pop_back();
                                            continue;
                                        }

                                        ++rowItor;

                                        for (row9Itor = mivsRow[8].begin(); row9Itor != mivsRow[8].end(); ++row9Itor)
                                        {
                                            int row9ColIndex = 0;
                                            vcTemp.clear();
                                            for (vector<char>::iterator itor9 = (*rowItor).begin();
                                                itor9 != (*rowItor).end(); ++itor9)
                                            {
                                                if (*itor9 == '.')
                                                {
                                                    vcTemp.push_back((*row9Itor)[row9ColIndex]);
                                                    ++row9ColIndex;
                                                }
                                                else
                                                {
                                                    vcTemp.push_back(*itor9);
                                                }
                                            }

                                            vvcTemp.push_back(vcTemp);

                                            if (isValidSudoku(vvcTemp))
                                            {
                                                board = vvcTemp;
                                                return;
                                            }
                                            else
                                            {
                                                vvcTemp.pop_back();
                                                continue;
                                            }
                                        }
                                        vvcTemp.pop_back();
                                        --rowItor;
                                    }
                                    vvcTemp.pop_back();
                                    --rowItor;
                                }
                                vvcTemp.pop_back();
                                --rowItor;
                            }
                            vvcTemp.pop_back();
                            --rowItor;
                        }
                        vvcTemp.pop_back();
                        --rowItor;
                    }
                    vvcTemp.pop_back();
                    --rowItor;
                }
                vvcTemp.pop_back();
                --rowItor;
            }
            vvcTemp.pop_back();
            --rowItor;
        }
    }

    void GenerateArray(vector<string> vArray, vector<string> &vResult)
    {
        vector<string>::iterator itor = vArray.begin();
        for (; itor != vArray.end(); ++itor)
        {
            GenerateArray(*itor, vResult);
        }
    }

    void GenerateArray(string str, vector<string>& vStr)
    {
        vector<string> vTemp;
        vTemp.clear();

        if (vStr.empty())
        {
            for (size_t index = 0; index < str.length(); ++index)
            {
                string s = "";
                s += str[index];
                vTemp.push_back(s);
            }
        }

        for (vector<string>::iterator itor = vStr.begin(); itor != vStr.end(); ++itor)
        {
            for (size_t index = 0; index < str.length(); ++index)
            {
                if ((*itor).find(str[index]) != string::npos)
                    continue;

                string s = *itor;
                s += str[index];
                vTemp.push_back(s);
            }
        }

        vStr.clear();
        for (vector<string>::iterator itor = vTemp.begin(); itor != vTemp.end(); ++itor)
        {
            vStr.push_back(*itor);
        }
    }

    bool isValidSudoku(vector<vector<char> >& vvc)
    {
        vector<vector<char> >::iterator vvItor = vvc.begin();
        //如果一行当中出现两个相同的数字,肯定是不合法的数独
        //如果一列当中出现两个相同的数字,也肯定是不合法的数独
        map<int, string> mColInfo;
        //每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;
                }
            }
        }

        return true;
    }
};

string GetCurrentModuleAddr()
{
    char chPath[256] = { 0 };
#ifdef WIN32
    GetModuleFileNameA(NULL, chPath, 256);
    printf("%s\n", chPath);
#else
    getcwd(chPath, 256);
    printf("%s\n", chPath);
#endif

    string sPath(chPath);

#ifdef WIN32
    int iPos = sPath.find_last_of('\\');
    if (iPos != string::npos)
    {
        sPath = sPath.substr(0, iPos + 1);
    }
    else if ((iPos = sPath.find_last_of('/')) != string::npos)
    {
        sPath = sPath.substr(0, iPos + 1);
    }
    else
    {
        return "";
    }
#else
    sPath += "/";
#endif
    return sPath;
}

int main(int argc, char **argv)
{
    vector<string> vStr;
    //之前6m25.284s 现在0m12.740s
    //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");

    //入门数独
    //0m0.026s
    //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..");

    //初级  2m9.907s  0m36.374s
    //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");

    //中级 超时
    //vStr.push_back(".....9..3");
    //vStr.push_back(".........");
    //vStr.push_back("58.......");
    //vStr.push_back(".........");
    //vStr.push_back("...2..65.");
    //vStr.push_back(".93..7...");
    //vStr.push_back(".2.54..8.");
    //vStr.push_back("..1.....7");
    //vStr.push_back("...6.....");

    //中级 0m3.284s
    //vStr.push_back("...5...82");
    //vStr.push_back(".6..7.9..");
    //vStr.push_back("9.5......");
    //vStr.push_back("6.39.274.");
    //vStr.push_back(".146..3..");
    //vStr.push_back("..9..35.6");
    //vStr.push_back("72...5...");
    //vStr.push_back("......25.");
    //vStr.push_back("..8.4...7");

    string sPath = GetCurrentModuleAddr();
    if (sPath.empty())
    {
        printf("cann't get file path\n");
        return -1;
    }

    FILE *fp;
    fp = fopen(string(sPath + "sudoku.txt").c_str(), "r");
    if (!fp)
    {
        printf("cann't open sudoku.txt!\n");
        return -1;
    }

    char *chBuff = new char[20];
    memset(chBuff, 0, 20);
    while (fgets(chBuff, 19, fp) != NULL)
    {
        string str(chBuff);
        str.erase(str.length() - 1, 1);
        vStr.push_back(str);
    }
    fclose(fp);

    //高级 20170704 超时
    //vStr.push_back("6.......7");
    //vStr.push_back(".....3...");
    //vStr.push_back(".7...1...");
    //vStr.push_back("......13.");
    //vStr.push_back("......8..");
    //vStr.push_back("4..69....");
    //vStr.push_back(".857.....");
    //vStr.push_back("...4....2");
    //vStr.push_back(".3.......");

    //高级 20170702  0m0.111s
    //vStr.push_back("2.54.7...");
    //vStr.push_back("1478...2.");
    //vStr.push_back("..3..5...");
    //vStr.push_back(".......82");
    //vStr.push_back("52..9.7.6");
    //vStr.push_back("764.8239.");
    //vStr.push_back("9..6..25.");
    //vStr.push_back("..6....3.");
    //vStr.push_back(".5..396.4");

    //高级 20170701 超时
    //vStr.push_back(".7...1...");
    //vStr.push_back("...6..5.8");
    //vStr.push_back("......4..");
    //vStr.push_back("1....7.9.");
    //vStr.push_back("..4......");
    //vStr.push_back("....3....");
    //vStr.push_back("....5....");
    //vStr.push_back("...4...2.");
    //vStr.push_back("79.....1.");

    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");
    }

    system("pause");
    return 0;
}


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值