最近在刷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;
}