poj 3074
数独问题,暴搜。
有一个优化,优先搜索可填位置少的
同时一个位置一个位置填,一次一个位置就好
可以用二进制储存状态
#include<cstdio> #include<algorithm> #define REP(i, a, b) for(register int i = (a); i < (b); i++) #define _for(i, a, b) for(register int i = (a); i <= (b); i++) using namespace std; const int MAXN = 15; int r[MAXN], c[MAXN], k[MAXN]; int lg[1 << 10], num[1 << 10]; char s[MAXN * MAXN], a[MAXN][MAXN]; inline int ID(int i, int j) { return 3 * (i / 3) + j / 3; } inline void draw(int x, int y, int z) { r[x] ^= 1 << z; c[y] ^= 1 << z; k[ID(x, y)] ^= 1 << z; } bool dfs(int cnt) { if(cnt == 81) return true; int x, y, mint = 10; REP(i, 0, 9) REP(j, 0, 9) if(a[i][j] == '.') { int val = num[r[i] & c[j] & k[ID(i, j)]]; if(!val) return false; if(mint > val) { mint = val; x = i, y = j; } } int tmp = r[x] & c[y] & k[ID(x, y)]; for(; tmp; tmp -= tmp & (-tmp)) { int t = lg[tmp & (-tmp)]; a[x][y] = t + '1'; draw(x, y, t); if(dfs(cnt + 1)) return true; draw(x, y, t); a[x][y] = '.'; } return false; } int main() { REP(i, 0, 9) lg[1 << i] = i; REP(i, 0, 1 << 9) for(int j = i; j; j -= j & (-j)) num[i]++; while(scanf("%s", s) && s[0] != 'e') { int cnt = 0; REP(i, 0, 9) c[i] = r[i] = k[i] = (1 << 9) - 1; REP(i, 0, 9) REP(j, 0, 9) { a[i][j] = s[i * 9 + j]; if(a[i][j] != '.') cnt++, draw(i, j, a[i][j] - '1'); } dfs(cnt); REP(i, 0, 9) REP(j, 0, 9) s[i * 9 + j] = a[i][j]; puts(s); } return 0; }