#include <stdio.h>
#include <string.h>
#include<iostream>
using namespace std;
#define MAX_N 9
#define MAX_NODES_STACK 81*MAX_N //栈的大小
#define MAX_NODES_QUEUE 500000*MAX_N //队列大小
typedef struct state_t{
short n; char _state[81]; //n表示当前已经填好的空格个数,_state表示这一个空格中填入的数字
} state_t;
state_t queue[MAX_NODES_QUEUE]; //构建队列
int head=0,tail=0; //head和tail分别指向队列首部和尾部
#define pop() stack[--sp] //弹出栈顶节点
#define push(node) stack[sp++] = node //将生成的新节点压入栈中
#define stack_not_empty (sp>0) //检查栈是否为空
#define get_node() queue[head++] //弹出队首节点
#define put_node(st) queue[tail++] = st //将新节点放入队尾
#define queue_not_empty (head<tail) //检查队列是否非空
char digit_Map[9][9]={0}; //初始状态
int blank_R[81]={0},blank_C[81]={0}; //blank_R与blank_C,分别表示空格的行与列
int blank_Num=0,help=1; //blank_Num表示空格的数量,help辅助判断
state_t stack[MAX_NODES_STACK]; //构建栈
int sp = 0; //指向栈顶
bool jud(int R,int C,char num,state_t *st);//判断在R行C列填入数字num是否和已有数字冲突
void DFS(int n); //尝试用深搜填满n个空格的数独表格
void BFS(int n); //尝试用宽搜填满n个空格的数独表格
void read(); //读取数独表格
void print_Map(state_t *st); //打印当前状态的数独表格
int main( )
{
state_t init_st;
read();
init_st.n = 0;
push(init_st); //将初始节点压入栈内
put_node(init_st); //将初始节点放入队列
DFS(blank_Num); //开始深搜
cout<<"深搜完成"<<endl;
system("pause");
BFS(blank_Num); //开始宽搜
cout<<"宽搜完成"<<endl;
system("pause");
return 0;
}
void read()//读取数度表格,记录空格坐标
{
for(int i=0;i<9;i++)
{
for(int j=0;j<9;j++)
{
cin>>digit_Map[i][j];
//记录空格坐标
if(digit_Map[i][j]=='0')
{
blank_R[blank_Num]=i;
blank_C[blank_Num]=j;
blank_Num++;
}
}
}
}
void print_Map(state_t *st)//打印当前状态数独表格
{
cout<<endl;
for(int k=0;k<blank_Num;k++)
{
digit_Map[blank_R[k]][blank_C[k]]=st->_state[k];
cout<<"第"<<k+1<<"步:"<<endl;
for(int i=0;i<9;i++)
{
for(int j=0;j<9;j++)
{
cout<<digit_Map[i][j];
}
cout<<endl;
}
}
for(int k=0;k<blank_Num;k++)
{
digit_Map[blank_R[k]][blank_C[k]]='0';
}
}
//判断在R行C列填入num是否与已有数据冲突
bool jud(int R,int C,char num,state_t *st)
{
char temp_Map[9][9]={0};
for(int k=0;k<9;k++)strcpy(temp_Map[k],digit_Map[k]);
//填入已有数字
if(st->n>1)for(int k=0;k<st->n-1;k++)
{
temp_Map[blank_R[k]][blank_C[k]]=st->_state[k];
}
for(int i=0;i<9;i++)//判断同一行是否冲突
{
if(temp_Map[R][i]==num)
{
return true;
}
}
for(int j=0;j<9;j++)//判断同一列是否冲突
{
if(temp_Map[j][C]==num)
{
return true;
}
}
for(int i=R/3*3;i<R/3*3+3;i++)//判断同一块是否冲突
{
for(int j=C/3*3;j<C/3*3+3;j++)
{
if(temp_Map[i][j]==num)
{
return true;
}
}
}
return false;
}
void DFS(int n)
{
int i, nCount=0;
help=1;
state_t st;
char temp=0;
while(stack_not_empty)
{
st = pop();
if (st.n>=n)//已填满所有空格,打印,help变为0,结束搜索过程
{
if(help)print_Map(&st);
nCount ++;
help=0;
continue;
}
st.n++;//当前填好的空格个数+1
for(i=0; i<9; i++)
{
temp='1'+i;
//1~9逐个判断是否与之前的数字冲突
if (jud(blank_R[st.n-1],blank_C[st.n-1],temp,&st))
{
continue;
}
st._state[st.n-1] = temp;//不冲突,该空格填入temp
push(st); //将新生成的节点压入栈
}
}
printf("\n共有%d种解法\n", nCount);//输出解法个数
return;
}
void BFS(int n)
{
int i, nCount=0;
help=1;
state_t st;
char temp=0;
while(queue_not_empty)
{
st = get_node();
if (st.n>=n)//已填满所有空格,打印,help变为0,结束搜索过程
{
if(help)print_Map(&st);
nCount ++;
help=0;
continue;
}
st.n++; //当前填好的空格个数+1
for(i=0; i<9; i++)
{
temp='1'+i;
//1~9逐个判断是否与之前的数字冲突
if (jud(blank_R[st.n-1],blank_C[st.n-1],temp,&st))
{
continue;
}
st._state[st.n-1] = temp;//不冲突,该空格填入temp
put_node(st); //将新生成的节点放入队列
}
}
printf("\n共有%d种解法\n", nCount);//输出解法个数
return;
}