题目: biubiu
题意:给一个残缺的数独,要求填入数字1~9,然后满足行和列1 ~ 9只能出现一遍,9 X9的数独又分成了3X3的小数独,保证小数独里面1 ~ 9也只出现一遍。
思路:采用深搜dfs,首先记录一下已经出现过的数字标记为1,然后就可以递归暴力将剩余的数字放进去,知道满足条件即可。
#include<iostream>
#include<vector>
#include<algorithm>
#include<map>
using namespace std;
class Solution {
public:
bool dfs(vector<vector<char>>& board,int hang[9][10], int lie[9][10], int a[3][3][10],int x) {
if (x >= 9)
return true;
for (int i = x; i < 9; i++) {
for (int j = 0; j < 9; j++) {
if (board[i][j] == '.') {
int k=0;
for ( k = 1; k <= 9; k++) {
if (!hang[i][k] && !lie[j][k] && !a[i / 3][j / 3][k]) {
hang[i][k] = 1;
lie[j][k] = 1;
a[i / 3][j / 3][k] = 1;
board[i][j] = '0' + k;
if(dfs(board, hang, lie, a, i))
return true;
hang[i][k] = 0;///回溯,说明k不符合,将其状态变为可以放
lie[j][k] = 0;
a[i / 3][j / 3][k] = 0;
}
}
if (k > 9) {
board[i][j] ='.';///回溯,在进行递归之前,修改了这个值,目前状态说明已没有符合条件的数能够放下,因此变回‘.‘
return false;
}
}
}
}
return true;
}
void solveSudoku(vector<vector<char>>& board) {
int hang[9][10] = {0};///标记,记录数字的出现
int lie[9][10] = { 0 };
int a[3][3][10] = { 0 };
for (int i = 0; i < 9; i++) {
for (int j = 0; j < 9; j++) {
if (board[i][j] >= '0' && board[i][j] <= '9') {
int x = board[i][j] - '0';
hang[i][x] = 1;
lie[j][x] = 1;
a[i / 3][j / 3][x] = 1;
}
}
}
dfs(board, hang, lie, a, 0);
}
};
int main() {
vector<vector<char>>board(9);
while (1) {
vector<vector<char>>board;
board.clear();
board.resize(9);
for (int i = 0; i < 9; i++) {
board[i].resize(9);
for (int j = 0; j < 9; j++) {
//char ch;
cin >>board[i][j];
//board[i][j] = ch;
cin.get();
}
}
cout << "*********" << endl;
///打印是否这个数独存储正确
for (int i = 0; i < 9; i++) {
for (int j = 0; j < 9; j++)
cout << board[i][j] << " ";
cout << endl;
}
cout << "******" << endl;
Solution s;
s.solveSudoku(board);
for (int i = 0; i < 9; i++) {
for (int j = 0; j < 9; j++)
cout << board[i][j] << " ";
cout << endl;
}
}
return 0;
}