武士数独求解思路+代码实现(部分)

武士数独求解问题
老师布置了一个作业,用代码求解武士数独问题,我直接用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;
}

  • 6
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值