问题描述:给你多个数独题目,让你输出答案
思路:递归确定每一个‘?’的位置的值,直到所有‘?’都被确定。先将原字符数组转换为整型数组,‘?’由数字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,' '); char2int(a,b); //char数组转换为int数组 if(dfs(b)) //产生结果 coutint(b); //输出数组内容 while(cin.getline(a[0],20,' ')){ //读取空行,或者到文件尾 cout<<endl; char a[9][20]; int b[9][9]; int i; for(i=0;i<9;i++) cin.getline(a[i],20,' '); char2int(a,b); //char数组转换为int数组 if(dfs(b)) //产生结果 coutint(b); //输出数组内容 } return 0; }