搜索_DFS_POJ3074_Sudoku

版权声明:本文为博主原创作品, 转载请注明出处! https://blog.csdn.net/solider98/article/details/84034211

点此打开题目页面

思路分析:

    使用DFS, 每次选择当前可填方案最少的空格对应分支进行递归, 并使用位运算进行优化, 需要注意的是如果不预先哈希lowblt将会TLE, 下面给出AC代码:

//POJ3074_Sudoku
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
int G[10][10], fix[10][10], R[10], C[10], A[10], ah[10][10], findd, cnt;
int lb[1 << 9];//lb[i]:i中1的个数 
int lowbit(int a){
	int ans = 0; while(a) a -= a & -a, ++ans; return ans;
}
//计算当前可选填数方案最少的空格 
pair<int, int> getMin(){
	int resx, resy, t = 10, f;
	for(int i = 1; i <= 9; ++i)
		for(int j = 1; j <= 9; ++j)
			if(!fix[i][j] && !G[i][j] && (f = lb[R[i] & C[j] & A[ah[i][j]]]) < t)
				t = f, resx = i, resy = j;
	return make_pair(resx, resy);
} 
void dfs(int x, int y){
	if(cnt == 81){
		for(int i = 1; i <= 9; ++i)
			for(int j = 1; j <= 9; ++j) cout << G[i][j];
		cout << endl, findd = 1; return;
	}
	for(int i = 1, k = ah[x][y], t = R[x] & C[y] & A[k]; i <= 9; ++i)
		if(t >> i - 1 & 1){
			G[x][y] = i, R[x] ^= 1 << i - 1, C[y] ^= 1 << i - 1, A[k] ^= 1 << i - 1, ++cnt;
			pair<int, int> nex = getMin(); dfs(nex.first, nex.second); if(findd) return;
			G[x][y] = 0, R[x] ^= 1 << i - 1, C[y] ^= 1 << i - 1, A[k] ^= 1 << i - 1, --cnt;
		}
}
int main(){
	char cstr[100]; for(int i = 1; i < 1 << 9; ++i) lb[i] = lowbit(i); 
	while(scanf("%s", cstr + 1), cstr[1] != 'e'){
		memset(G, 0, sizeof(G)), memset(fix, 0, sizeof(fix)), findd = 0, cnt = 0;
		for(int i = 1; i <= 9; ++i) R[i] = C[i] = A[i] = (1 << 9) - 1;
		for(int i = 1; i <= 9; ++i){
			for(int j = 1; j <= 9; ++j){
				int k = cstr[(i - 1) * 9 + j] == '.'? 0: cstr[(i - 1) * 9 + j] - '0';
				G[i][j] = k, ah[i][j] = 3 * (i / 3 - !(i % 3) * 1) + j / 3 + 1 - !(j % 3) * 1;
				if(k) 
					fix[i][j] = 1, R[i] ^= 1 << k - 1, C[j] ^= 1 << k - 1
					, A[ah[i][j]] ^= 1 << k - 1, ++cnt;
			}
		}		
		pair<int, int> begin = getMin(); dfs(begin.first, begin.second);
	}
	return 0;
} 

猜你喜欢

转载自blog.csdn.net/solider98/article/details/84034211