以前做过一道hdu类似的数独题,那道题我没有加什么优化就过了,然后这道题不加优化可以得50~80分,要上80分就必须要优化
可以用位运算保存每一行每一列每个九宫格内已经使用的数,例如userow[i] = 011101111表示第i行还有1,5两个数字没有使用,那么我们枚举每个未知的格子(i,j)时,他不能填的数就是userow[i]|usecol[j]|usebox[i/3*3+j/3] ,其实这样做也不能优化什么时间,下面才是最NB的优化
在输入的时候我们可以统计每一行已知的数,于是我们能够把没有填数的格子按每一行从小到大来排序,这样,枚举这个点能够扩展出来的搜索树就会比原来小。
#include<cstdio> #include<iostream> #include<cstring> #include<algorithm> #define RE ((1<<9)-1) using namespace std; int sum_a[10]; struct T { int x,y; bool operator < (T t) const//已知数多的放在前面 { if(sum_a[x] == sum_a[t.x]) return x < t.x; return sum_a[x] > sum_a[t.x]; } }unknown[100];//保存没有填的格子的位置 int st[10][10]; int p[10][10];//权值数组 void init() { for(int i = 0; i < 9; i++) { p[0][i] = p[8][i] = p[i][0] = p[i][8] = 6; } for(int i = 1; i < 8; i++) { p[1][i] = p[7][i] = p[i][1] = p[i][7] = 7; } for(int i = 2; i < 7; i++) { p[2][i] = p[6][i] = p[i][2] = p[i][6] = 8; } for(int i = 3; i < 6; i++) { p[3][i] = p[5][i] = p[i][3] = p[i][5] = 9; } p[4][4] = 10; } int ans = -1; int cnt,sorce; int userow[10];//每一行使用的数 int usecol[10];//每一列使用的数 int usebox[10];//每一个九宫格内使用的数 void dfs(int cur) { if(cur > cnt) { ans = max(sorce,ans); return; } int x = unknown[cur].x; int y = unknown[cur].y; int temp = (userow[x]|usecol[y]|usebox[x/3*3+y/3]); if(temp == RE) return;//没有可以使用的数 for(int i = 1; i <= 9; i++) if(!((temp>>(i-1))&1)) { st[x][y] = i; usebox[x/3*3+y/3] |= (1<<(i-1)); userow[x] |= (1<<(i-1)); usecol[y] |= (1<<(i-1)); sorce += st[x][y]*p[x][y]; dfs(cur+1); sorce -= st[x][y]*p[x][y]; st[x][y] = 0; usebox[x/3*3+y/3] ^= (1<<(i-1)); userow[x] ^= (1<<(i-1)); usecol[y] ^= (1<<(i-1)); } } int main() { //freopen("sudoku.in","r",stdin); //freopen("sudoku.out","w",stdout); init(); for(int i = 0; i < 9; i++) { for(int j = 0; j < 9; j++) { scanf("%d",&st[i][j]); if(st[i][j] != 0) { sorce += st[i][j]*p[i][j]; userow[i] |= (1<<(st[i][j]-1)); usecol[j] |= (1<<(st[i][j]-1)); usebox[i/3*3+j/3] |= (1<<(st[i][j]-1)); ++sum_a[i];//统计i行已知的数 } } } for(int i = 0; i < 9; i++) for(int j = 0; j < 9; j++) { if(!st[i][j]) { ++cnt; unknown[cnt].x = i; unknown[cnt].y = j; } } sort(unknown+1,unknown+cnt+1); dfs(1); printf("%d\n",ans); }
版权声明:本文为博主原创文章,未经博主允许不得转载。
时间: 2024-10-19 18:25:29