DFS剪枝数独(简单版)

Posted 行码棋

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了DFS剪枝数独(简单版)相关的知识,希望对你有一定的参考价值。

题目链接:

https://www.acwing.com/problem/content/168/


搜索以及剪枝策略:

  • 搜索顺序优化: 首先搜索可填最少数量数字的格子
  • 二进制优化:用两个数组row[], col[]存储每一行和每一列的可以填的数的状态,一共9位二进制,该位为1时代表可以选,为0时代表不可以选。
  • lowbit优化:取每一位可以选的数时采用的操作

代码解释:
mn:就是单元格中求 最小的可以填的个数
ones[i]i二进制中1的个数
dfs(cnt):代表从可以填cnt个数开始搜索

#include<bits/stdc++.h>
using namespace std;
using ll = long long;
const int N = 9;

int ones[1 << N], mp[1 << N];
int row[N], col[N], cell[3][3];
char s[100];
// 获取可以填的数的二进制状态
int get(int x, int y)

	return row[x] & col[y] & cell[x / 3][y / 3];

bool dfs(int cnt)

	if(!cnt) return true;

	int mn = 10;
	int x, y;
	for(int i = 0; i < N; i++)
		for(int j = 0; j < N; j++)
		
			if(s[i * N + j] == '.')
			
				int t = ones[get(i, j)];
				if(t < mn)
				
					mn = t;
					x = i, y = j;
				
			
		

	for(int i = get(x, y); i; i -= i & (-i))
	
		int t = mp[i & (-i)];
		row[x] -= 1 << t;
		col[y] -= 1 << t;
		cell[x / 3][y / 3] -= 1 << t;

		s[x * N + y] = '1' + t;

		if(dfs(cnt - 1)) return true;

		row[x] += 1 << t;
		col[y] += 1 << t;
		cell[x / 3][y / 3] += 1 << t;

		s[x * N + y] = '.';
	
	return false;

int main()

	ios::sync_with_stdio(false);
	cin.tie(0);

	for(int i = 0; i < N; i++) 
		mp[1 << i] = i;
	for(int i = 0; i < 1 << N; i++)
	
		int cnt = 0;
		for(int j = i; j; j -= j & (-j)) 
			cnt++;
		ones[i] = cnt;
	


	while(cin >> s, s[0] != 'e')
	
		for(int i = 0; i < N; i++)
			row[i] = col[i] = (1 << N) - 1;
		for(int i = 0; i < 3; i++)
			for(int j = 0; j < 3; j++)
				cell[i][j] = (1 << N) - 1;

		int cnt = 0;
		for(int i = 0, k = 0; i < N; i++)
			for(int j = 0; j < N; j++, k++)
			
				if(s[k] != '.')
				
					int t = s[k] - '1';
					row[i] -= (1 << t);
					col[j] -= (1 << t);
					cell[i / 3][j / 3] -= (1 << t);
				
				else cnt++;
			

		dfs(cnt);
		cout << s << "\\n";
	
 	return 0;

以上是关于DFS剪枝数独(简单版)的主要内容,如果未能解决你的问题,请参考以下文章

[dfs] aw166. 数独(dfs剪枝与优化+状态压缩+代码技巧+好题)

HDU-6341 Problem J. Let Sudoku Rotate(dfs 剪枝)

Luogu P1074靶形数独

P1074靶形数独

[NOIP2009] 靶形数独(搜索+剪枝)

POJ2676 Sudoku - DFS