搜索法解数独程序,dfs
#include <iostream>
#include <fstream>
#include <cctype>
#include <fstream>
using namespace std;
#define N 9
#define M 3
int Sudoku[N][N] = {0};
int cnt = 0;//记录解的个数
bool x[N][N] = {0};//x[i][j]代表第i行是否存在数j
bool y[N][N] = {0};//y[i][j]代表第i列是否存在数j
bool z[N][N] = {0};//z[i][j]代表第i个九宫格是否存在数j
bool flag = false;//只想输出一个解时的状态位
void Print(int Sudoku[][N])
{
for (int i = 0; i < N;++i)
{
for (int j = 0; j < N;++j)
{
cout << Sudoku[i][j] << " ";
}
cout << endl;
}
cout << endl;
}
/*判断位置(i,j)是否能放置n*/
inline bool IsSafe(int i,int j,int n)
{
return !(x[i][n] || y[j][n] || z[i / M * M + j / M][n]);
}
bool PlaceNumber(int i,int j,int n)
{
if (IsSafe(i, j, n))
{
Sudoko[i][j] = n + 1;
x[i][n] = true;
y[j][n] = true;
z[i / M * M + j / M][n] = true;
return true;
}
else
return false;
}
/*回朔放置程序*/
void BackPlace(int i, int j)
{
int n = 0;
if (i == N)
{
Print(Sudoku);
++cnt;
}
else if (j == N)
{
BackPlace(i + 1, 0);
}
else if (Sudoku[i][j] != 0)
BackPlace(i, j + 1);
else
while (n < N)
{
if (PlaceNumber(i, j, n))
{
BackPlace(i, j + 1);
x[i][n] = false;
y[j][n] = false;
z[i / M * M + j / M][n] = false;
}
++n;
};
if (n >= N && Sudoku[i][j] != 0)
Sudoku[i][j] = 0;
}
int main()
{
char num;
int i = 0 ,j = 0, n = 1;
fstream file;
char filename[] = "Sudoku.txt";
file.open(filename);
/*.............................loading.............................*/
for (i = 0;i < N;++i)
for (j = 0;j < N;++j)
{
file >> num;
if (isdigit(num))
Sudoku[i][j] = num - '0';
if (Sudoko[i][j] != 0)
if (IsSafe(i, j, Sudoku[i][j] - 1))
{
x[i][Sudoku[i][j] - 1] = true;
y[j][Sudoku[i][j] - 1] = true;
z[i / M * M + j / M][Sudoku[i][j] - 1] = true;
}
else
{
cout << "input Sudoku error" << endl;
return -1;
}
}
BackPlace(0, 0);
cout << "Total " << cnt << " answers." << endl;
system("pause");
return 0;
}
Sudoko.txt文件内容示例
000070000
200050097
700000500
007000205
000060804
003080709
365009478
978546123
142030956
然后是DLX,比上面的方法效率高非常多,适合大量数据的情况
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#define MAX 240000
#define BIG 0x3f3f3f3f
#define N 9
int u[MAX],d[MAX],l[MAX],r[MAX],x[MAX],y[MAX],cnt[1000],ans[100],e,deep;
char cc[100];
void rev(int m)
{
int i,j;
l[r[m]]=l[m];
r[l[m]]=r[m];
for(i=d[m];i!=m;i=d[i])
for(j=r[i];j!=i;j=r[j])
{
u[d[j]]=u[j];
d[u[j]]=d[j];
cnt[y[j]]--;
}
}
void rem(int m)
{
int i,j;
for(i=u[m];i!=m;i=u[i])
for(j=l[i];j!=i;j=l[j])
cnt[y[u[d[j]]=d[u[j]]=j]]++;
l[r[m]]=r[l[m]]=m;
}
bool dfs(int dd)
{
int i,j,mn,c;
if(r[0]==0)
{
deep=dd;
return true;
}
for(mn=BIG,i=r[0];i;i=r[i])
if(mn>cnt[i])
{
mn=cnt[i];
c=i;
}
rev(c);
for(i=d[c];i!=c;i=d[i])
{
ans[dd]=x[i];
for(j=r[i];j!=i;j=r[j])
rev(y[j]);
if(dfs(dd+1))
return true;
for(j=l[i];j!=i;j=l[j])
rem(y[j]);
}
rem(c);
return false;
}
void addu(int m)
{
y[e]=++m;//M 为列
cnt[y[e]]++;
u[e]=u[m];
d[e]=m;
d[u[e]]=e;
u[d[e]]=e;
e++;
}
void add(int i,int j,int n)
{
x[e]=x[e+1]=x[e+2]=x[e+3]=i*N*N+j*N+n;//值。。。。。?!
l[e+1]=r[e+3]=e;
l[e+2]=r[e]=e+1;
l[e+3]=r[e+1]=e+2;
l[e]=r[e+2]=e+3;
addu(i*N+n);
addu(N*N+j*N+n);
addu(2*N*N+((i/3)*3+j/3)*N+n);
addu(3*N*N+i*N+j);
}
int main()
{
freopen("Sudoku.in", "r", stdin);
freopen("Sudoku.out", "w", stdout);
int a,b;
int i,j,k;
while(scanf("%s",cc))
{
if(cc[0]=='e')
break;
memset(cnt,0,sizeof(cnt));
for(e=4*N*N+1,i=0;i<e;i++)
{
u[i]=d[i]=i;
l[i]=(i+e-1)%e;
r[i]=(i+1)%e;
}
for(i=0;i<N;i++)
for(j=0;j<N;j++)
if(cc[i*N+j]=='.')
for(k=0;k<N;k++)
add(i,j,k);
else
add(i,j,cc[i*N+j]-'1');
dfs(0);
for(i=0;i<deep;i++)
cc[ans[i]/N]=ans[i]%N+'1';
puts(cc);
}
system("pause");
return 0;
}
Sudoku.in存放每行数据
读入end程序结束