题目描述
思路
一开始,觉得应该对每个格子为0的进行dfs,为了进行顺序最优的dfs,要先从可选数量少的格子进行,这样对每个格子创建一个set,存储能够填的数。
然后就是根据size大小排序,选择最小的进行dfs。
然后发现每次dfs都要进行排序,set的二维数组得设在dfs函数内,排序的时候又得根据这个set数组的大小进行排序,对于cmp函数内访问的set应该是全局变量,又得设置一个全局变量的set二维数组保存每次dfs函数内创建的set数组,然后排序。
然后发现每次dfs只会选择数据量最小的进行排序,这样就不用使用二维数组,直接遍历的时候筛选处数据量最小的set就可以了。
然后就是这样做了之后,忘记判断有无解的情况,之后就是wrong answeer。
然后就是time limit exceed,按照书上说的dfs剪枝技巧,最起码现在完成了最优搜索顺序。
然后就是每次填数字其实影响的就只有行,列和小九宫格里面的数据选择,更新全部的话,显得重复,不更新全部,代码有点难写。dfs就麻烦在剪枝上,剪不掉就会造成超时,真烦人。
然后就是可以采用状态压缩的方式保存格子的数据选择集合。
然后就是去掉set,改用位运算的方式实现上述的算法,终于过了,可见set是多么的耗时。
代码
#include <cstdio>
#include <cstring>
int mp[9][9], ans;
const int wq = 511;
bool flag = false;
int val[9][9] = {
6, 6, 6, 6, 6, 6, 6, 6, 6,
6, 7, 7, 7, 7, 7, 7, 7, 6,
6, 7, 8, 8, 8, 8, 8, 7, 6,
6, 7, 8, 9, 9, 9, 8, 7, 6,
6, 7, 8, 9,10, 9, 8, 7, 6,
6, 7, 8, 9, 9, 9, 8, 7, 6,
6, 7, 8, 8, 8, 8, 8, 7, 6,
6, 7, 7, 7, 7, 7, 7, 7, 6,
6, 6, 6, 6, 6, 6, 6, 6, 6,
};
bool get(int x, int y, int &z) {
int k = 0;
for (int i = 0; i < 9; ++i) {
if (mp[x][i] != 0) k |= 1 << (mp[x][i] - 1);
if (mp[i][y] != 0) k |= 1 << (mp[i][y] - 1);
}
int a = x / 3 * 3, b = y / 3 * 3;
for (int i = 0; i < 3; ++i) {
for (int j = 0; j < 3; ++j) {
if (mp[a + i][b + j] != 0) k |= 1 << (mp[a + i][b + j] - 1);
}
}
z = wq ^ k;
return z == 0;
}
int getbit(int x) {
int y = 0;
while (x) {
if (x & 1) ++y;
x >>= 1;
}
return y;
}
bool mysort(int &x, int &y, int &z) {
z = wq;
int b = 0;
for (int i = 0; i < 9; ++i) {
for (int j = 0; j < 9; ++j) {
if (mp[i][j] == 0) {
if (get(i, j, b)) return false;
if (getbit(b) < getbit(z)) z = b, x = i, y = j;
}
}
}
return true;
}
void dfs(int res) {
int x, y, z = 0;
if (!mysort(x, y, z)) return;
if (getbit(z) == 9) {
flag = true;
if (res > ans) ans = res;
return;
}
int k = 0;
while (z) {
if (z & 1) {
mp[x][y] = k + 1;
dfs(res + mp[x][y] * val[x][y]);
mp[x][y] = 0;
}
z >>= 1;
k++;
}
}
int main() {
for (int i = 0; i < 9; ++i) {
for (int j = 0; j < 9; ++j) {
scanf("%d", &mp[i][j]);
if (mp[i][j] != 0) ans += mp[i][j] * val[i][j];
}
}
dfs(ans);
if (flag) printf("%d
", ans);
else puts("-1");
return 0;
}