数独问题
145327698
839654127
672918543
496185372
218473956
753296481
367542819
984761235
521839764
解法1(按坐标):
数独问题(以列为主):
都是同一行、同一列以及在小矩阵中不存在与之相同而且当前位置没有被放置数字也就是此处为0;
其中,确定该位置所在的小矩阵是根据其所在小矩阵的左上角坐标而定,
因为是根据坐标进行回溯所以起始为(0,0)~(n-1,n-1)
当(x==n && y==n)时到达解空间,此时的矩阵是满足条件的
当回溯到一个位置时有两种可能:
(1)此处已经存在数字,
①如果是最后一列并且是最后一行,直接输出该结果
②如果是最后一列不是最后一行,进行当前列下一行的位置traceback(x+1,y);
③如果不是最后一列,是最后一行则 traceback(0,y+1);
④如果既不是最后一列又不是最后一行则traceback(x+1,y)
(2)此处没有数字
首先应该将此位置进行赋值,该位置可以放置 1~n
放置数字之后进行判断该数字放在此处是否合适,如果合适则进行如上4步判断
如果不合适,则放置下一数字。
#include <stdio.h>
#define n 9
int a[n][n]={
0,0,5,3,0,0,0,0,0,
8,0,0,0,0,0,0,2,0,
0,7,0,0,1,0,5,0,0,
4,0,0,0,0,5,3,0,0,
0,1,0,0,7,0,0,0,6,
0,0,3,2,0,0,0,8,0,
0,6,0,5,0,0,0,0,9,
0,0,4,0,0,0,0,3,0,
0,0,0,0,0,9,7,0,0};
bool ok(int x, int y) //二者分别是数组对应的行地址和列地址,取值为0-8
{
int up, down, left, right;
int i,j;
up=x/3*3;
down=up+3;
left=y/3*3;
right=left+3;
//以下分三种情况判断是否在x,y对应的位置放这个数,如果不可以放,返回0,如果可以放,返回1,会进一步迭代
for(i=0;i<9;i++){
if(a[x][y]==a[i][y] && i!=x && a[i][y]!=0)
return false;
}
for(i=0;i<9;i++){
if (a[x][y]==a[x][i] && i!=y && a[x][i]!=0)
return false;
}
for(i=up;i<down;i++)
{
for(j=left;j<right;j++)
if(i!=x || j!=y)
{
if(a[i][j]==a[x][y] && a[i][j]!=0)
return false;
}
}
return true;
}
void traceback(int x,int y){//按a[x][y]的坐标回溯
if(a[x][y]!=0){
if(y==n-1){
if(x==n-1){
printf("=============\n");
for (int i=0; i<9; i++) {
for (int j =0; j <9; j++) {
printf("%d ",a[i][j]);
}
printf("\n");
}
}
else
traceback(x+1,y);
}
else{
if(x==n-1)
traceback(0,y+1);
else
traceback(x+1,y);
}
}
else{
for(int i=1;i<10;i++){
a[x][y]=i;
if(ok(x,y)){//如果可以放
if(y==n-1){
if(x==n-1){
for (int i=0; i<9; i++) {
for (int j =0; j <9; j++) {
printf("%d ",a[i][j]);
}
printf("\n");
}
}
else
traceback(x+1,y);
}
else{
if(x==n-1)
traceback(0,y+1);
else
traceback(x+1,y);
}
}
a[x][y]=0;
}
}
}
int main()
{
traceback(0,0);
return 0;
}
解法2(按编号):
矩阵的判断与按坐标回溯相同。
按照编号进行回溯的时候,一共 n*n 个位置所以当 t==n*n 时到达解空间直接输出矩阵结果
此时位置的坐标变成了:x=t/9; y=t%9;
当不到解空间时有两种可能:
(1)此处已经存在数字,
直接进行下一位置的判断
(2)此处没有数字
首先应该将此位置进行赋值,该位置可以放置 1~n
放置数字之后进行判断该数字放在此处是否合适,如果合适则进行下一位置的判断(dfs(t+1))
如果不合适,则放置下一数字。
#include <stdio.h>
#define n 9
int a[n][n]={
0,0,5,3,0,0,0,0,0,
8,0,0,0,0,0,0,2,0,
0,7,0,0,1,0,5,0,0,
4,0,0,0,0,5,3,0,0,
0,1,0,0,7,0,0,0,6,
0,0,3,2,0,0,0,8,0,
0,6,0,5,0,0,0,0,9,
0,0,4,0,0,0,0,3,0,
0,0,0,0,0,9,7,0,0};
bool ok(int x, int y)
{
int up, down, left, right;
int i,j;
up=x/3*3;
down=up+3;
left=y/3*3;
right=left+3;
for(i=0;i<9;i++){
if(a[x][y]==a[i][y] && i!=x && a[i][y]!=0)
return false;
}
for(i=0;i<9;i++){
if (a[x][y]==a[x][i] && i!=y && a[x][i]!=0)
return false;
}
for(i=up;i<down;i++)
{
for(j=left;j<right;j++)
if(i!=x || j!=y)
{
if(a[i][j]==a[x][y] && a[i][j]!=0)
return false;
}
}
return true;
}
void dfs(int t)
{
if(t==81)
{
for(int i=0;i<n;i++){
for(int j=0;j<n;j++)
{
printf("%d ",a[i][j]);
}
printf("\n");
}
}
else{
int x=t/9;
int y=t%9;
if(a[x][y]!=0)
{
dfs(t+1);
}else{
for(int i=1;i<10;i++)
{
a[x][y]=i;
if(ok(x,y))
{
dfs(t+1);
}
a[x][y]=0;
}
}
}
}
int main()
{
dfs(0);
return 0;
}