【4】数独(Sudoku Killer)(深度优先遍历)

时间:2019-03-18
本文章向大家介绍【4】数独(Sudoku Killer)(深度优先遍历),主要包括【4】数独(Sudoku Killer)(深度优先遍历)使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

问题描述:给你多个数独题目,让你输出答案

思路:递归确定每一个‘?’的位置的值,直到所有‘?’都被确定。先将原字符数组转换为整型数组,‘?’由数字0代替,然后每一次层递归找到第一个0的位置,如果找到了,找出当前位置所有可以放置的数字,依次尝试,每次假设把这个数放在当前位置,然后再确认下一个0位置的数字,直到数组中找不到0,即是正确结果(递归出口)。

#include <stdio.h>
#include <iostream>

using namespace std;

 void coutint(int b[9][9])    //输出整型二维数组
 {
     int i,j;
     for(i=0;i<9;i++){
         for(j=0;j<9;j++)
             if(j!=8)
                 cout<<b[i][j]<<' ';
             else
                 cout<<b[i][j];
         cout<<endl;
     }
 }
 
 void char2int(char a[9][20],int b[9][9])    //字符二维数组向整型二维数组转换
 {
     int i,j;
     for(i=0;i<9;i++)
         for(j=0;j<18;j++)
             if(a[i][j]=='?')
                 b[i][j/2] = 0;
             else if('1'<=a[i][j] && a[i][j]<='9')
                 b[i][j/2] = a[i][j]-'0'; //字符转化为整型
 }
 
 bool judge(int curx,int cury,int num,const int b[9][9])
 {
     int i,j;
     //查找一横行
     for(i=0;i<9;i++)    //将这一行出现的数字全部设为不可填
         if(i!=cury && b[curx][i]==num)
             return true;
     //查找一竖列
     for(i=0;i<9;i++)    //将这一行出现的数字全部设为不可填
         if(i!=curx && b[i][cury]==num)
             return true;
     //查找当前九宫格
     int x,y;
     x = curx/3*3;
     y = cury/3*3;
     for(i=0;i<3;i++)
         for(j=0;j<3;j++)
             if(x+i!=curx && y+j!=cury && b[x+i][y+j]==num)
                 return true;
     return false;
 }
 
 bool dfs(int b[9][9])
 {
     //找到当前第一个'?'位置。如果没有找到,表示所有位置都已填上,即为正确结果,递归结束
     int i,j;
     for(i=0;i<9;i++)
         for(j=0;j<9;j++)
             if(b[i][j]==0)    //找'?'的位置
                 goto label;            
     label:
     if(i>=9 && j>=9)    //找到正确结果了,递归结束
         return true;
     //记录坐标
     int curx = i,cury = j;
     //确定该位置的可以填的数字
     bool temp[10];    //记录哪些数字可以填
     int num=0;    //记录当前位置可以填的数字的个数
     for(i=1;i<=9;i++)
         if(judge(curx,cury,i,b))    //判断这个位置可不可以放这个数字
             temp[i] = false;
         else {
             temp[i] = true;
             num++;
         }
     if(num==0)
         return false;
     //确定下一个位置
     for(i=1;i<=9;i++)
         if(temp[i]){
             //这个数在这个位置可以填
             if(judge(curx,cury,i,b))
                 continue;
             b[curx][cury] = i;
             if(dfs(b))
                 return true;
         }
     b[curx][cury] = 0;    //这句千万别忘了写,就是这一步不能走的记得还原为0
     return false;
 }
 int main()
 {
     char a[9][20];
     int b[9][9];
     int i;
     for(i=0;i<9;i++)
         cin.getline(a[i],20,'\n');
     char2int(a,b);    //char数组转换为int数组
     if(dfs(b))    //产生结果
         coutint(b);    //输出数组内容
 
     while(cin.getline(a[0],20,'\n')){    //读取空行,或者到文件尾
         cout<<endl;
         char a[9][20];
         int b[9][9];
         int i;
         for(i=0;i<9;i++)
             cin.getline(a[i],20,'\n');
         char2int(a,b);    //char数组转换为int数组
         if(dfs(b))    //产生结果
             coutint(b);    //输出数组内容
     }
     return 0;
 }