链接:
https://www.acwing.com/problem/content/168/
题意:
数独是一种传统益智游戏,你需要把一个9 × 9的数独补充完整,使得图中每行、每列、每个3 × 3的九宫格内数字1~9均恰好出现一次。
请编写一个程序填写数独。
思路:
二进制记录每一行, 每一列, 每一块的数值使用情况, 每次从最小的开始枚举.
代码:
#include <bits/stdc++.h> using namespace std; char input[90]; char Map[10][10]; int Cnt[1000], Num[1000]; int row[10], col[10], gri[10]; int cnt; int Lowbit(int x) { return x&(-x); } int GetP(int x, int y) { return (x/3)*3+(y/3); } void Change(int x, int y, int p) { row[x] ^= (1<<p); col[y] ^= (1<<p); gri[GetP(x, y)] ^= (1<<p); } bool Dfs(int las) { // cout << las << endl; if (las == 0) return true; int tmp = 10, x, y; for (int i = 0;i < 9;i++) { for (int j = 0;j < 9;j++) { if (Map[i][j] != '.') continue; int val = row[i]&col[j]&gri[GetP(i, j)]; if (val == 0) return false; if (Cnt[val] < tmp) { tmp = Cnt[val]; x = i, y = j; } } } int val = row[x]&col[y]&gri[GetP(x, y)]; while (val > 0) { int z = Num[Lowbit(val)]; Map[x][y] = z+'1'; Change(x, y, z); if (Dfs(las-1)) return true; Change(x, y, z); Map[x][y] = '.'; val -= Lowbit(val); } return false; } int main() { for (int i = 0;i < (1<<9);i++) { for (int j = i;j > 0;j -= Lowbit(j)) Cnt[i]++; } for (int i = 0;i < 9;i++) Num[1<<i] = i; while (scanf("%s", input) && input[0] != 'e') { for (int i = 0;i < 9;i++) { for (int j = 0;j < 9;j++) Map[i][j] = input[i*9+j]; } for (int i = 0;i < 9;i++) row[i] = col[i] = gri[i] = (1<<9)-1; cnt = 0; for (int i = 0;i < 9;i++) { for (int j = 0;j < 9;j++) { if (Map[i][j] != '.') Change(i, j, Map[i][j]-'1'); else cnt++; } } Dfs(cnt); for (int i = 0;i < 9;i++) { for (int j = 0;j < 9;j++) input[i*9+j] = Map[i][j]; } puts(input); } return 0; }