武士数独求解问题
老师布置了一个作业,用代码求解武士数独问题,我直接用dfs+一些优化做出来了(偷了一个大懒,具体大家看代码吧),图片就是武士数独,时间关系就不排版了。核心代码就是dfs函数,我用answer封装了一下,优化思路的话acwing,y总有教过。因为老师给的题目比较简单,每个99的数独都有唯一解,我就偷懒了,想要真正地实现代码,我提供一个思路:把中间的99数独的解全部求解出来,然后在依次求解剩余的四个。为啥这样,就自己想吧(累了,老师还不一定改)。
直接上代码
#include<bits/stdc++.h>
using namespace std;
const int N=9;
int nums;
int ones[1<<N];//记录每个整数二进制的表达式中有多少个1
int f1[1<<N];//二进制与整数的映射
int row[N] , col[N] , cell[3][3];//约束条件
//inline关键字,可以加速非递归函数的编译时速度
inline int lowbit(int x){//(返回x最低位为1对应的二进制数)
return x & -x;
}
//初始化
void init(){
for(int i=0 ; i < N; i++) row[i] = col[i] = (1 << N) - 1;//更新行列的可选数位1-9用二进制表示
//同理9*9
for(int i = 0 ; i < 3 ; i++)//(3x3)
for(int j = 0 ; j < 3 ; j++ )
cell[i][j] = ( 1 << N) - 1;
}
inline int get(int x,int y){
return row[x] & col[y] & cell[x/3][y/3];//求解当前行和列中的的可选数的二进制表示
}
int dfs(int cnt,char str [][9],char res[][9]){
//如果没有空格则结束递归
if(!cnt){
//(输出方案)
for(int i = 0 ; i < 9 ; i++){
for(int j = 0 ; j < 9 ; j++){
res[i][j] = str[i][j];
}
}
nums++;
}else{
//找出可选方案数最少的空格
int minv = 10;
int x , y;//(记录最少空格的坐标)
for(int i = 0 ; i < N ; i++)
for(int j = 0 ; j < N ; j++)
if(str[i][j] == '.'){
int t = ones[get(i,j)];
if(t < minv){
minv = t;
x = i;
y = j;
}
}
for(int i=get(x,y) ; i ; i -= lowbit(i)){
int t = f1[lowbit(i)];
//修改状态
row[x] -= 1 << t;
col[y] -= 1 << t;
cell[x/3][y/3] -= 1 << t;
str[x][y] = '1' + t;
dfs(cnt - 1 , str , res);
//恢复现场
str[x][y] = '.';
cell[x/3][y/3] += 1 << t;
col[y] += 1 << t;
row[x] += 1 << t;
}
}
return nums;
}
int answer(char str [][9] , char res[][9]){
nums = 0;//记录9*9数独解的个数
for(int i = 0;i< N ; i++) f1[1<<i] = i;
for(int i = 0;i< 1 << N; i++){
int s = 0;
for(int j = i; j ; j -= lowbit(j)) s++;//i的二进制中有s个1
ones[i] = s;
}
init();//初始化
int cnt = 0;
for(int i = 0 ; i < N; i++)
for(int j = 0 ; j < N ; j++)
if(str[i][j] != '.'){//(修改每行每列,每个3x3在此坐标处可选数字集合)
int t = str[i][j] - '1';
row[i] -= 1 << t;
col[j]-= 1 << t;
cell[i/3][j/3] -= 1 << t;
}
else cnt++;//(记录有多少个空格)
int nums = dfs(cnt,str,res);//(递归深搜)
return nums;
}
int main(){
/*
{'.', '.', '.', '5', '.', '.', '9', '2', '7'},
{'2', '3', '.', '1', '7', '9', '.', '6', '.'},
{'.', '.', '.', '.', '4', '.', '.', '3', '5'},
{'1', '.', '3', '4', '.', '.', '.', '.', '.'},
{'.', '.', '.', '.', '.', '8', '.', '.', '.'},
{'8', '.', '.', '.', '.', '2', '.', '.', '.'},
{'.', '1', '4', '7', '2', '.', '.', '.', '6'},
{'6', '.', '.', '9', '3', '1', '7', '.', '.'},
{'.', '7', '2', '8', '.', '4', '.', '.', '.'}
{'.', '.', '.', '.', '.', '.', '.', '.', '.'},
{'.', '8', '.', '.', '7', '.', '.', '3', '.'},
{'.', '.', '.', '.', '.', '.', '.', '.', '.'},
{'7', '.', '.', '.', '1', '.', '.', '.', '3'},
{'.', '.', '.', '.', '.', '6', '.', '.', '.'},
{'.', '.', '2', '.', '.', '.', '4', '.', '.'},
{'.', '.', '.', '.', '5', '.', '.', '.', '.'},
{'.', '4', '.', '.', '6', '.', '.', '9', '.'},
{'6', '.', '.', '.', '.', '.', '3', '.', '.'}
*/
//第一组
char str6[][9]= {
{'.', '.', '.', '.', '.', '.', '.', '.', '.'},
{'.', '.', '.', '.', '.', '.', '.', '.', '.'},
{'.', '.', '.', '.', '.', '.', '.', '.', '.'},
{'.', '.', '.', '2', '5', '8', '.', '.', '.'},
{'.', '.', '.', '.', '9', '4', '.', '.', '.'},
{'.', '.', '.', '.', '.', '1', '.', '.', '.'},
{'.', '.', '.', '.', '.', '.', '.', '.', '.'},
{'.', '.', '.', '.', '.', '.', '.', '.', '.'},
{'.', '.', '.', '.', '.', '.', '.', '.', '.'}
};
char str3[][9]= {
{'.', '.', '.', '.', '1', '6', '.', '.', '.'},
{'.', '2', '.', '.', '.', '.', '.', '1', '8'},
{'.', '8', '.', '2', '.', '3', '4', '.', '.'},
{'2', '.', '.', '.', '.', '.', '.', '.', '9'},
{'.', '.', '4', '.', '.', '.', '6', '.', '3'},
{'.', '.', '5', '.', '.', '.', '.', '2', '1'},
{'.', '4', '.', '.', '.', '.', '.', '.', '.'},
{'.', '.', '9', '.', '.', '8', '3', '5', '7'},
{'8', '.', '.', '.', '5', '.', '.', '.', '.'}
};
char str1[][9]= {
{'.', '2', '3', '.', '.', '7', '5', '.', '.'},
{'.', '.', '7', '.', '.', '.', '1', '.', '.'},
{'.', '.', '4', '.', '.', '3', '8', '.', '.'},
{'3', '.', '.', '.', '6', '8', '.', '9', '.'},
{'1', '.', '.', '.', '7', '2', '6', '.', '5'},
{'.', '.', '.', '5', '.', '.', '.', '.', '.'},
{'.', '.', '.', '8', '.', '.', '.', '.', '.'},
{'.', '9', '.', '.', '.', '.', '.', '2', '.'},
{'.', '4', '6', '.', '.', '.', '.', '8', '.'}
};
char str2[][9]= {
{'3', '.', '4', '.', '.', '7', '.', '2', '.'},
{'.', '.', '.', '.', '2', '.', '.', '8', '.'},
{'.', '8', '.', '5', '.', '1', '.', '.', '.'},
{'5', '.', '.', '.', '.', '.', '3', '.', '.'},
{'6', '2', '.', '4', '.', '.', '.', '.', '1'},
{'.', '.', '7', '.', '.', '.', '.', '.', '.'},
{'.', '.', '.', '.', '.', '6', '.', '.', '5'},
{'.', '1', '8', '9', '.', '.', '.', '.', '.'},
{'4', '.', '.', '8', '1', '3', '7', '.', '.'}
};
char str4[][9]= {
{'.', '8', '.', '.', '.', '.', '.', '4', '.'},
{'.', '3', '5', '.', '.', '7', '.', '.', '9'},
{'.', '.', '4', '.', '2', '5', '8', '.', '.'},
{'.', '.', '.', '.', '.', '.', '.', '.', '8'},
{'.', '6', '9', '.', '.', '.', '4', '2', '.'},
{'.', '.', '.', '.', '.', '.', '1', '.', '.'},
{'6', '7', '.', '8', '.', '.', '.', '.', '1'},
{'.', '4', '.', '2', '.', '.', '.', '.', '5'},
{'.', '.', '1', '.', '7', '.', '3', '.', '.'}
};
char str5[][9]= {
{'.', '.', '.', '.', '.', '.', '.', '7', '.'},
{'3', '5', '7', '8', '.', '2', '.', '.', '.'},
{'.', '.', '.', '.', '.', '7', '.', '1', '3'},
{'.', '.', '.', '.', '2', '.', '.', '9', '.'},
{'5', '.', '.', '9', '.', '.', '.', '.', '.'},
{'6', '.', '.', '.', '8', '3', '.', '.', '.'},
{'8', '.', '2', '4', '.', '.', '7', '.', '.'},
{'.', '.', '.', '.', '9', '.', '2', '.', '.'},
{'.', '4', '3', '.', '.', '5', '.', '.', '.'}
};
char res[5][9][9];
char final[21][21]={'.'} ;
int res1 = answer(str1,res[0]);
int res2 = answer(str2,res[1]);
int res3 = answer(str3,res[2]);
int res4 = answer(str4,res[3]);
int res5 = answer(str5,res[4]);
for(int i = 0 ; i < 9 ; i++){
for(int j = 0 ; j < 9 ; j++){
final[i][j] = res[0][i][j];
}
}
for(int i = 0 ; i < 9 ; i++){
for(int j = 12 ; j < 21 ; j++){
final[i][j] = res[1][i][j-12];
}
}
for(int i = 6; i <6+9 ; i++){
for(int j = 6; j <6+9 ; j++){
final[i][j] = res[2][i-6][j-6];
}
}
for(int i = 12 ; i < 12 + 9 ; i++){
for(int j = 0 ; j < 9 ; j++){
final[i][j] = res[3][i-12][j];
}
}
for(int i = 12 ; i < 12+9 ; i++){
for(int j = 12 ; j < 12+9 ; j++){
final[i][j] = res[4][i-12][j-12];
}
}
for(int i = 0; i < 21 ; i++){
for(int j = 0 ; j < 21 ; j++){
cout<<final[i][j]<<" ";
}
cout<<endl;
}
cout<<endl;
//第二组
char str33[][9]= {
{'.', '.', '.', '.', '.', '.', '5', '.', '.'},
{'.', '6', '.', '.', '.', '.', '.', '7', '.'},
{'7', '.', '2', '8', '6', '.', '.', '.', '4'},
{'.', '.', '4', '.', '1', '3', '.', '.', '2'},
{'6', '.', '.', '.', '.', '.', '.', '1', '.'},
{'.', '.', '.', '9', '2', '.', '.', '.', '5'},
{'.', '4', '.', '.', '.', '8', '.', '.', '7'},
{'.', '5', '.', '3', '.', '4', '1', '.', '.'},
{'9', '.', '.', '.', '.', '.', '.', '.', '.'}
};
char str11[][9]= {
{'.', '.', '1', '.', '2', '.', '3', '.', '7'},
{'.', '4', '.', '.', '.', '7', '6', '2', '.'},
{'.', '.', '.', '.', '.', '.', '9', '.', '.'},
{'.', '.', '4', '5', '1', '9', '.', '7', '.'},
{'.', '.', '.', '4', '.', '3', '2', '9', '.'},
{'.', '6', '.', '.', '.', '.', '.', '.', '.'},
{'.', '2', '.', '.', '.', '5', '.', '.', '.'},
{'.', '7', '.', '.', '9', '.', '.', '6', '.'},
{'.', '.', '6', '8', '.', '.', '7', '.', '2'}
};
char str22[][9]= {
{'.', '9', '.', '.', '.', '.', '.', '.', '.'},
{'.', '.', '2', '7', '.', '3', '.', '.', '.'},
{'7', '.', '.', '1', '5', '.', '.', '.', '6'},
{'.', '1', '.', '.', '.', '9', '8', '.', '.'},
{'2', '.', '.', '5', '.', '.', '.', '6', '.'},
{'.', '.', '.', '6', '1', '.', '.', '.', '.'},
{'5', '.', '.', '4', '3', '.', '.', '.', '9'},
{'.', '7', '.', '9', '2', '6', '3', '4', '.'},
{'.', '.', '4', '.', '.', '.', '.', '.', '1'}
};
char str44[][9]= {
{'5', '9', '2', '.', '7', '.', '.', '4', '.'},
{'.', '.', '.', '1', '.', '.', '.', '5', '.'},
{'3', '.', '6', '5', '.', '.', '9', '.', '.'},
{'8', '.', '.', '.', '2', '.', '.', '.', '.'},
{'7', '.', '.', '.', '.', '.', '8', '.', '3'},
{'.', '2', '.', '.', '.', '6', '.', '.', '.'},
{'.', '.', '.', '.', '6', '.', '.', '.', '9'},
{'.', '4', '.', '.', '.', '.', '1', '.', '.'},
{'.', '5', '.', '9', '.', '.', '7', '.', '4'}
};
char str55[][9]= {
{'.', '.', '7', '.', '.', '.', '.', '.', '9'},
{'1', '.', '.', '.', '.', '4', '.', '.', '3'},
{'.', '.', '.', '9', '.', '2', '.', '.', '.'},
{'8', '.', '.', '3', '.', '.', '.', '.', '.'},
{'.', '.', '.', '4', '.', '.', '.', '7', '.'},
{'.', '.', '.', '.', '2', '.', '1', '.', '4'},
{'.', '.', '2', '.', '.', '7', '.', '5', '8'},
{'.', '.', '6', '.', '.', '.', '.', '4', '.'},
{'9', '.', '5', '.', '.', '.', '2', '.', '1'}
};
char ress[5][9][9];
char finall[21][21]={'.'} ;
int res11 = answer(str11,ress[0]);
int res22 = answer(str22,ress[1]);
int res33 = answer(str33,ress[2]);
int res44 = answer(str44,ress[3]);
int res55 = answer(str55,ress[4]);
// for(int i = 0 ; i < 5 ; i++){
// for(int j = 0 ; j < 9 ; j++){
// for(int k = 0 ; k < 9 ; k ++){
// cout<<ress[i][j][k]<<" ";
// }
// cout<<endl;
// }
// cout<<endl;
// }
for(int i = 0 ; i < 9 ; i++){
for(int j = 0 ; j < 9 ; j++){
finall[i][j] = ress[0][i][j];
}
}
for(int i = 0 ; i < 9 ; i++){
for(int j = 12 ; j < 21 ; j++){
finall[i][j] = ress[1][i][j-12];
}
}
for(int i = 6; i <6+9 ; i++){
for(int j = 6; j <6+9 ; j++){
finall[i][j] = ress[2][i-6][j-6];
}
}
for(int i = 12 ; i < 12 + 9 ; i++){
for(int j = 0 ; j < 9 ; j++){
finall[i][j] = ress[3][i-12][j];
}
}
for(int i = 12 ; i < 12+9 ; i++){
for(int j = 12 ; j < 12+9 ; j++){
finall[i][j] = ress[4][i-12][j-12];
}
}
for(int i = 0; i < 21 ; i++){
for(int j = 0 ; j < 21 ; j++){
cout<<finall[i][j]<<" ";
}
cout<<endl;
}
return 0;
}