1. 程式人生 > >搜尋_DFS_CH2901_靶形數獨

搜尋_DFS_CH2901_靶形數獨

點此開啟題目頁面

思路分析:

    使用DFS, 每次選擇候選填數方案最少的分支遞歸併結合位運算優化即可, 具體如下AC程式碼所示:

//CH2901_靶形數獨
#include <iostream>
#include <cstdio>
#include <cmath>
using namespace std;
int G[10][10], fix[10][10];//fix[i][j]非零表示G[i][j]初始給出
int R[10], C[10], A[10];//R[i]第i行可填的數, C[i]第i列可填的數, A[i]第i個9宮格可填的數
int ah[10][10];//ah[i][j]:G[i][j]對應9宮格編號
int res = -1, val, cnt;//cnt:當前已經填好的數個數
int lowbit(int a){
	int ans = 0; while(a) a -= a & -a, ++ans; return ans;	
} 
void dfs(int x, int y){
	if(cnt == 81){
		res = max(res, val); return;  
	}
	for(int i = 1, k = ah[x][y], t = A[k] & R[x] & C[y], s = max(abs(x - 5), abs(y - 5))
		; 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
			, val += i * (10 - s), ++cnt;
			int nexx, nexy, tmp = 10, f;
			for(int p = 1; p <= 9; ++p)
				for(int q = 1; q <= 9; ++q)
					if(!fix[p][q] && !G[p][q] && (f = lowbit(R[p] & C[q] & A[ah[p][q]])) < tmp)
						tmp = f, nexx = p, nexy = q;
			dfs(nexx, nexy);
			G[x][y] = 0, R[x] ^= 1 << i - 1, C[y] ^= 1 << i - 1, A[k] ^= 1 << i - 1
			, val -= i * (10 - s), --cnt;
		}
}
int main(){
	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){
			scanf("%d", &G[i][j]);
			ah[i][j] = 3 * (i / 3 - !(i % 3) * 1) + j / 3 + 1 - !(j % 3) * 1;
			if(G[i][j]) 
				fix[i][j] = 1, R[i] ^= 1 << G[i][j] - 1, C[j] ^= 1 << G[i][j] - 1
				, A[ah[i][j]] ^= 1 << G[i][j] - 1, ++cnt
				, val += G[i][j] * (10 - max(abs(i - 5), abs(j - 5)));
		}
	int nexx, nexy, tmp = 10, f;
	for(int p = 1; p <= 9; ++p)
		for(int q = 1; q <= 9; ++q)
			if(!fix[p][q] && (f = lowbit(R[p] & C[q] & A[ah[p][q]])) < tmp)
				tmp = f, nexx = p, nexy = q;
	dfs(nexx, nexy), cout << res << endl;
}