【DFS】Ybt_数独游戏

题目大意

给你一些数独题,让你填。
空位以 ‘.’ 表示,多组数据,以end结尾。


深度搜索,剪枝。
用二进制位压缩储存状态,用这个以判断当前位置可以填的数字。


代码

#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;

int l[20], h[20], z[5][5], k[20][20], flag;
char c;

char getc(){
    
      //输入
	char lc = getchar();
	while(( lc>'9' || lc<'0' ) && lc != '.' && lc != 'e') lc = getchar();
	return lc;
}

void init(){
    
      //输入
	memset(l, 0, sizeof(l));
	memset(h, 0, sizeof(h));
	memset(z, 0, sizeof(z));
	for(int i = 1; i <= 9; ++i){
    
    
		for(int j = 1; j <= 9; ++j){
    
    
	  		if(c != '.'){
    
    
	  			k[i][j] = c-48;
	  			l[j] += 1 << (c-48-1);  //列,这个数的状态为1(填过)
	  			h[i] += 1 << (c-48-1);  //行,这个数的状态为1(填过)
	  			z[(i+2)/3][(j+2)/3] += 1 << (c-48-1); //小矩阵,这个数的状态为1(填过)
			}
			else k[i][j] = 0;
			c = getc();
	    }
	}   
}

void printt(){
    
      //输出
	for(int i = 1; i <= 9; ++i)
	    for(int j = 1; j <= 9; ++j)
	  		printf("%d", k[i][j]);
	printf("\n");
}

void dfs(int bh){
    
    
	if(bh > 81){
    
      //找到答案
		flag = 1;
		printt();
		return;
	}
	int x = (bh+8) / 9, y = (bh-1) % 9 + 1;  //当前点坐标
	int jzx = (x+2) / 3, jzy = (y+2) / 3;  //小矩阵是哪一个
	if(k[x][y] != 0) dfs(bh + 1);  //如果它本来就给出了这个数
	else for(int i = 1; i <= 9; ++i){
    
      //枚举
		if((h[x] >> (i-1)) % 2 == 0)  //行没出现
		if((l[y] >> (i-1)) % 2 == 0)  //列没出现
		if((z[jzx][jzy] >> (i-1)) % 2 == 0){
    
      //小矩阵没出现
	  		h[x] += 1 << (i-1);  //改变状态
			l[y] += 1 << (i-1);
	  		z[jzx][jzy] += 1 << (i-1);
	  		k[x][y] = i;  //记录答案
	  		dfs(bh+1);
	  		k[x][y] = 0;
	  		if(flag == 1) return;
	  		h[x] -= 1 << (i-1);
			l[y] -= 1 << (i-1);
	  		z[jzx][jzy] -= 1 << (i-1);
		}
	}
}

int main(){
    
    
	c = getc();
	while(c!='e'){
    
      //多组数据
	 	init();
	 	flag = 0;
	 	dfs(1);
	}
} 

猜你喜欢

转载自blog.csdn.net/qq_42937087/article/details/112388089
今日推荐