1 条题解
-
0
#include<bits/stdc++.h> using namespace std; const int N = 9; int row[N], col[N], cell[3][3]; string str; int ones[1 << N], mp[1 << N]; //ones数组得到二进制数1的个数,mp得到二进制数下任何一个位置的1能填的数字是几 int lowbit(int x) { return x & -x; } void init() { 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 get(int x, int y) { return row[x] & col[y] & cell[x / 3][y / 3]; } bool dfs(int cnt) { if(cnt == 0) return true; //找到可填数字最少的点 int minv = 10; int x, y; for(int i = 0; i < N; i++) for(int j = 0; j < N; j++) if(str[i * 9 + j] == '.') { int t = ones[get(i, j)]; if(t < minv) { minv = t; x = i, y = j; } } //该点枚举所有能填的数字 for(int i = get(x, y); i; i -= lowbit(i)) // i = 101000100 { int t = mp[lowbit(i)]; //修改 row[x] -= 1 << t; col[y] -= 1 << t; cell[x / 3][y / 3] -= 1 << t; str[x*9 + y] = '1' + t; if(dfs(cnt - 1)) return true; row[x] += 1 << t; col[y] += 1 << t; cell[x / 3][y / 3] += 1 << t; str[x * 9 + y] = '.'; } return false; } int main() { for(int i = 0; i < N; i++) mp[1 << i] = i; for(int i = 0; i < 1 << N; i++) { int s = 0; for(int j = i; j; j -= lowbit(j)) s++; ones[i] = s; //i的二进制数中1的个数 } while(cin >> str && str != "end") { init(); //预处理三个数组 int cnt = 0; //表示要填多少个数字 for(int i = 0, k = 0; i < N; i++) for(int j = 0; j < N; j++, k++) if(str[k] != '.') { int t = str[k] - '1'; //数字从0 - 8 row[i] -= 1 << t; //将二进制数的第t位变成0 col[j] -= 1 << t; cell[i/3][j/3] -= 1 << t; } else cnt ++; dfs(cnt); cout << str << endl; } return 0; } /* row[i] col[j] cell[i/3][j/3] 爆搜的过程: 1.选择一个未填数字的格子,该格子能填的数字个数是最少的 每个点,行列九宫格数字的个数 填数字 2.枚举格子可以填的数字 lowbit 以及 映射数组快速得到 3.dfs下个 4.....8.5 .3....... ...7..... .2.....6. ....8.4.. ....1.... ...6.3.7. 5..2..... 1.4...... 优化搜索顺序 ok 排除冗余信息 可行性剪枝 最优性剪枝 */
- 1
信息
- ID
- 100
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 7
- 标签
- 递交数
- 30
- 已通过
- 8
- 上传者