#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
今日推荐
周排行