规则:
数字 1-9 在每一行只能出现一次。 数字 1-9 在每一列只能出现一次。 数字 1-9 在每一个以粗实线分隔的 3x3 宫内只能出现一次。 空白格用 '.' 表示。
乍一看解数独和N皇后问题很像,甚至会更难些,但其实我觉得二者是差不多的,在解数独的代码里,会加入一个二维的结构,但是其实我们不必那样想,数独是一个9*9的表格,我们可以将其拆成一条竖下来的线,即第二行接到第一行末尾,第三行接到第二行末尾......
这样一来,整个表格就成了一个竖向的表格,其中每一个格子都有1~9可能性,这与n皇后的每一层就非常相似了。
回溯算法
解数独只有一种正确解法,我们只需要找到即可,不需要结果集来搜集,回溯函数的返回值设置为bool,一旦满足条件(最后一个格子也遍历)即返回,结束函数。
bool backtarcking(vector<vector<char>>& chess)
{
//两个for循环遍历完即找到结果
for(int i=0;i<9;i++)
{
for(int j=0;j<9;j++)
{
if(chess[i][j]!='.')
{
continue;
}
else
{
for(int k='1';k<='9';k++)
{
if(IsVaild(i,j,k,chess))
{
chess[i][j]=k;
//一旦找到,直接一路回溯
if(backtracking(chess))
{
return true;
}
continue;
}
}
//当1~9都没有合适的,说明上面错误。
//返回错误答案,回溯。
chess[i][j]='.';
return false;
}
}
}
return true;
}
判断
bool IsVaild(int x,int y,int k,vector<vector<char>>& chess)
{
for(int i=0;i<chess.size();i++)
{
if(chess[i][y]==k)
{
return false;
}
}
for(int j=0;j<chess[0].size();j++)
{
if(chess[x][j]==k)
{
return false;
}
}
//3*3方格内不能重复数字
for(int ix=(x/3)*3;ix<(x/3)*3+3;ix++)
{
for(int iy=(y/3)*3;iy<(y/3)*3+3;iy++)
{
if(chess[ix][iy]==k)
{
return false;
}
}
}
return true;
}
整体代码
#include <iostream>
#include <vector>
using namespace std;
class solution
{
private:
bool backtracking(vector<vector<char>>& chess)
{
for(int i=0;i<chess.size();i++)
{
for(int j=0;j<chess[0].size();j++)
{
if(chess[i][j]!='.')
{
continue;
}
else
{
for(char k='1';k<='9';k++)
{
if(IsVaild(i, j, k,chess))
{
chess[i][j]=k;
if(backtracking(chess))
{
return true;
}
else
{
//chess[i][j]='.';
continue;
}
}
else
{
continue;
}
}
chess[i][j]='.';
return false;
}
}
}
return true;
}
bool IsVaild(int x,int y,int k,vector<vector<char>> chess)
{
for(int i=0;i<chess.size();i++)
{
if(chess[i][y]==k)
{
return false;
}
}
for(int j=0;j<chess[0].size();j++)
{
if(chess[x][j]==k)
{
return false;
}
}
for(int ix=(x/3)*3;ix<(x/3)*3+3;ix++)
{
for(int iy=(y/3)*3;iy<(y/3)*3+3;iy++)
{
if(chess[ix][iy]==k)
{
return false;
}
}
}
return true;
}
public:
void results(vector<vector<char>>& chess)
{
backtracking(chess);
}
};
int main() {
std::cout << "Hello World!\n";
vector<vector<char>> chess={{'5','3','.','.','7','.','.','.','.'},
{'6','.','.','1','9','5','.','.','.'},
{'.','9','8','.','.','.','.','6','.'},
{'8','.','.','.','6','.','.','.','3'},
{'4','.','.','8','.','3','.','.','1'},
{'7','.','.','.','2','.','.','.','6'},
{'.','6','.','.','.','.','2','8','.'},
{'.','.','.','4','1','9','.','.','5'},
{'.','.','.','.','8','.','.','7','9'},};
solution so;
so.results(chess);
for(auto i:chess)
{
for(auto j:i)
{
cout<<j<<' ';
}
cout<<endl;
}
}