深搜与宽搜实现解数独

#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;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值