b_lc_解数独(巧妙保存3*3方格的状态)
Write a program to solve a Sudoku puzzle by filling the empty cells.
A sudoku solution must satisfy all of the following rules:
- Each of the digits 1-9 must occur exactly once in each row.
- Each of the digits 1-9 must occur exactly once in each column.
- Each of the the digits 1-9 must occur exactly once in each of the 9 3x3 sub-boxes of the grid.
Empty cells are indicated by the character '.'.
方法一:回溯
py暴力解法
class Solution:
def solveSudoku(self , g ):
def chk_row(x,y,c):
for i in range(9):
if g[x][i]==c: return False
return True
def chk_col(x,y,c):
for i in range(9):
if g[i][y]==c: return False
return True
def chk_area(x,y,c):
sx,sy=x//3*3,y//3*3 #将(x,y)定位到所属小九宫格的左上角位置
for i in range(3):
for j in range(3):
if g[sx+i][sy+j]==c:
return False
return True
def dfs(s,g):
if s==ALL:
return True
x,y=s//n,s%m
if g[x][y]!='.':
if dfs(s+1,g): return True
return False
else:
for i in range(1,10):
nc=str(i)
if chk_row(x,y,nc) and chk_col(x,y,nc) and chk_area(x,y,nc):
g[x][y]=nc
if dfs(s+1,g): return True
g[x][y]='.'
return False
n,m,ALL=len(g),len(g[0]),81
dfs(0,g)
这里处理3×3方格得很巧妙,对 x/3,y/3 后会使3×3方格中任何一格的坐标变为相同,这样就方便用状态记录数组记录;
注:这里的行和列的状态要分开记录
const int N=10;
class Solution {
public:
int n, m, st_r[N][10], st_c[N][10], st_box[N][N][10];
bool dfs(int x, int y, vector<vector<char>>& g) {
if (y==m) return dfs(x+1, 0, g);
if (x==n) return true;
if (g[x][y]=='.') {
for (char c='1'; c<='9'; c++) {
int num=c-'0';
if (!st_r[x][num] && !st_c[y][num] && !st_box[x/3][y/3][num]) {
g[x][y]=c;
st_r[x][num]=st_c[y][num]=st_box[x/3][y/3][num]=1;
if (dfs(x,y+1,g)) return true;
st_r[x][num]=st_c[y][num]=st_box[x/3][y/3][num]=0;
g[x][y]='.';
}
}
return false;
} else {
return dfs(x,y+1,g);
}
}
void solveSudoku(vector<vector<char>>& g) {
n=g.size(), m=g[0].size();
for (int i=0; i<n; i++)
for (int j=0; j<m; j++) {
if (g[i][j]!='.') {
int num=g[i][j]-'0';
st_r[i][num]=st_c[j][num]=st_box[i/3][j/3][num]=true;
}
}
dfs(0,0,g);
}
};