神仙思路
这道题用的方式非常之神仙,用位运算来判断数字的选与不选。首先我们先来构造几个辅助数组,以便把映射数组\(X,Y,Box\)的值预先求出,然后再处理几个位运算的辅助数组。由于做法过于神仙,难以解释,看代码就好。
代码
// POJ3074.cpp #include <iostream> #include <cstdio> #include <algorithm> #define lowbit(number) (number & (-number)) using namespace std; char sequence[81]; int X[81], Y[81], Box[81], slist[(1 << 9)], counters[(1 << 9)]; int sx[81], sy[81], sb[81], n, tmp; void setStat(int i, int k) { tmp = 1 << k, sx[X[i]] ^= tmp, sy[Y[i]] ^= tmp, sb[Box[i]] ^= tmp; } int getSlot(int num) { int cnt = 0; while (num > 0) cnt++, num -= lowbit(num); return cnt; } bool dfs(int remain) { if (remain == 0) return true; int min_val = 10, val_id; for (int i = 0; i < 81; i++) if (sequence[i] == '.') { int comb = sx[X[i]] & sy[Y[i]] & sb[Box[i]]; if (counters[comb] < min_val) min_val = counters[comb], val_id = i; } int comb = sx[X[val_id]] & sy[Y[val_id]] & sb[Box[val_id]]; while (comb > 0) { int nbit = slist[lowbit(comb)]; sequence[val_id] = nbit + '1'; setStat(val_id, nbit); if (dfs(remain - 1)) return true; setStat(val_id, nbit); sequence[val_id] = '.'; comb -= lowbit(comb); } return false; } int main() { for (int i = 0; i < 81; i++) X[i] = i / 9, Y[i] = i % 9, Box[i] = (int)(X[i] / 3) * 3 + Y[i] / 3; for (int i = 0; i < 9; i++) slist[1 << i] = i; for (int i = 0; i < (1 << 9); i++) counters[i] = getSlot(i); while (scanf("%s", sequence) && sequence[0] != 'e') { // initailize the fact; n = 0; for (int i = 0; i < 81; i++) sx[i] = sy[i] = sb[i] = (1 << 9) - 1; for (int i = 0; i < 81; i++) if (sequence[i] != '.') setStat(i, sequence[i] - '1'); else n++; if (dfs(n)) printf("%s\n", sequence); } return 0; }