166.数独
#include <iostream> #include <algorithm> #include <stdlib.h> #include <string> using namespace std; const int N = 9, M = 1 << N; char str[100]; int Row[N], Line[N], Block[3][3]; // 哪些数字可以填, 1可以填写, 0 不能填写 int Log[M], cnt[M], Empty; void Deal(int x, int y, int num, int f) { if (f < 0) str[x * 9 + y] = num + '1'; else str[x * 9 + y] = '.'; int Target = (1 << num) * f; Row[x] += Target; Line[y] += Target; Block[x / 3][y / 3] += Target; } int query(int x, int y) { int tmp = Row[x] & Line[y] & Block[x / 3][y / 3]; return cnt[tmp]; } int lowbit(int x) { return x & (-x); } bool dfs(int Done) { if (Done == 0) { return true; } int tx = -1, ty = -1, m = 0x3f3f3f3f; for (int i = 0; i < 9; i++) for (int j = 0; j < 9; j++) { if(str[i * 9 + j] != '.') continue; int tmp = query(i, j); if (tmp < m) { m = tmp; tx = i; ty = j; } } int State = Row[tx] & Line[ty] & Block[tx / 3][ty / 3]; for(int i = State; i; i -= lowbit(i)) { int tmp = lowbit(i); int Pos = Log[tmp]; Deal(tx, ty, Pos, -1); if(dfs(Done - 1)) return true; Deal(tx, ty, Pos, 1); } return false; } void init() { for (int i = 0; i < N; i++) Row[i] = Line[i] = (1 << N) - 1; for (int i = 0; i < 3; i++) for (int j = 0; j < 3; j++) Block[i][j] = (1 << N) - 1; } int main() { for (int i = 0; i < N; i++) Log[1 << i] = i; for (int i = 0; i < M; i++) for (int j = 0; j < N; j++) cnt[i] += i >> j & 1; while (cin >> str && str[0] != 'e') { init(); Empty = 0; for (int i = 0, Now = 0; i < 9; i++) for (int j = 0; j < 9; j++, Now++) { if (str[Now] != '.') Deal(i, j, str[Now] - '1', -1); else Empty++; } dfs(Empty); puts(str); } return 0; }
写的时候太马虎大意了,dfs忘记加最重要的判断语句:
if(str[i * 9 + j] != '.') continue;
导致一直搜不出来
一开始想用每一位数的0表示没填过(即还可以填) 1反之
但写到一半才意识到这种写法是不可取的
因为如果这么写的话,为了配合lowbit运算,我们就需要对得到的结果数字进行取反。
但是我们的cnt数组只处理了0~1 << N 范围内的数字,取反之后会超出这个范围,导致计算出错,甚至产生segment fault
这道题还有个值得注意的点:
因为这道题不是找最优解或者统计方案数,所以不能写成void(void形式最终会找到所有的可行解,可能会TLE)
这道题需要写成bool形式,一旦当前搜索树的一棵子树找到了答案,就没有必要再继续搜索它的其他子树了,因为我们只需要一个可行解即可。
本文作者:Gold_stein
本文链接:https://www.cnblogs.com/smartljy/p/17826609.html
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步