位运算优化数独

#include <iostream>
#include <cstdlib>
#include <algorithm>
#include <vector> 

struct Sudoku {
    
     
	private:
		int blk[9], row[9], col[9];
		int A[9][9], lg[1024];
		
		int lowbit(int x) {
    
     /// 得到最低二进制位 
			return x & (-x);
		}
		int BLK(int i, int j) {
    
     /// 计算某个位置所在的块 
			return (i/3)*3 + (j/3);
		}
	
		std::vector<std::pair<int, int> > pos; /// 记录需要处理的位置 
		void DFS(int d) {
    
     /// 填数 
			if(d == pos.size()) {
    
    
				for(int i = 0; i <= 8; i ++) {
    
    
					for(int j = 0; j <= 8; j ++) {
    
    
						printf("%d ", A[i][j]);
					}
					putchar('\n');
				}
				putchar('\n');
			}else {
    
    
				int x = pos[d].first, y = pos[d].second;
				int avai = row[x] & col[y] & blk[BLK(x, y)];
		
				while(avai) {
    
    
					int n = lowbit(avai); /// 找到最低比特并尝试 
					avai ^= n;
					n = lg[n]; /// 找到对应的数字 
					
					A[x][y] = n;
					blk[BLK(x, y)] ^= (1<<(n-1));
					row[x] ^= (1<<(n-1));
					col[y] ^= (1<<(n-1));
					
					DFS(d + 1); /// 递归选择下一个位置 
					
					A[x][y] = 0;
					blk[BLK(x, y)] ^= (1<<(n-1));
					row[x] ^= (1<<(n-1));
					col[y] ^= (1<<(n-1));
				}
			}
		}
		
	public:
		Sudoku() {
    
    
			for(int i = 1; i <= 9; i ++) {
    
     /// 预处理取对数 
				lg[1<<(i-1)] = i;
			}
			for(int i = 0; i <= 8; i ++) {
    
    
				blk[i] = row[i] = col[i] = 0;
			}
			for(int i = 0; i < 8; i ++) {
    
    
				for(int j = 0; j < 8; j ++) {
    
    
					A[i][j] = 0;
				}
			}
		}
		int Solve(int B[9][9]) {
    
     /// B[i][j] = 0 表示该位置没有数 
			for(int i = 0; i <= 8; i ++) {
    
    
				for(int j = 0; j <= 8; j ++) {
    
     /// 坐标 [0, 8] 
					A[i][j] = B[i][j];
					if(A[i][j] != 0) {
    
    
						blk[BLK(i, j)] |= (1 << (A[i][j]-1));
						row[i] |= (1 << (A[i][j]-1));
						col[j] |= (1 << (A[i][j]-1)); /// 处理行列和块 
						/// col[j] 写成了 col[i] 调试了一天 qwq 
					}else {
    
    
						pos.push_back(std::make_pair(i, j));
					}
				}
			}
			for(int i = 0; i <= 8; i ++) {
    
    
				blk[i] = ((1<<9)-1) ^ blk[i]; /// 取反 
				row[i] = ((1<<9)-1) ^ row[i];
				col[i] = ((1<<9)-1) ^ col[i];
			}
			DFS(0);
			return 0;
		}
};

int B[9][9];
int main() {
    
    
	Sudoku* tmp = new Sudoku;
	for(int i = 0; i <= 8; i ++) {
    
    
		for(int j = 0; j<= 8; j ++) {
    
    
			scanf("%d", &B[i][j]);
		}
	}
	tmp -> Solve(B);
	return 0;
}

猜你喜欢

转载自blog.csdn.net/GGN_2015/article/details/115348528