soj 1162. Sudoku[Special judge] 1317. Sudoku
来源:互联网 发布:访客网络最大上传速度 编辑:程序博客网 时间:2024/05/18 22:46
两道数独求解的问题。
思路:
很显然,两道题目的思路都是,读入数据记录所有待求解的点,然后进行深搜即可。
但是不难看出的一点是,如果是单纯的暴力深搜,搜索的深度可能达到81,这样做可能会超时,于是要进行剪枝。
剪枝的方法很简单,预先算出进行下一步扩展的点的个数,然后进行排序,扩展点个数少的先搜索。
由于本题是求解数独,在最初的时候对各个待求解的点根据可能的情况数排序之后确定搜索的先后顺序即可。
方法:
记录每一行每一列每一个数字是否出现,记录所有带求解的点,深搜,剪枝。
1162 剪枝前代码:
#include <cstring>#include <cstdio>char square[10][10];bool row[10][10], col[10][10], blo[10][10];int x[85], y[85], todo, flag;int block(int i, int j) {return (i-1)/3*3 + (j-1)/3 + 1;}void dfs(int n){ if (flag || n == todo) { flag = 1; return; } int xx = x[n], yy = y[n], bl = block(xx,yy); for (int temp = 1; temp <= 9; ++ temp) { if (!row[xx][temp] && !col[yy][temp] && !blo[bl][temp]) { square[xx][yy] = temp+'0'; row[xx][temp] = 1; col[yy][temp] = 1; blo[bl][temp] = 1; dfs(n+1); if (flag) return; row[xx][temp] = 0; col[yy][temp] = 0; blo[bl][temp] = 0; } }}int main(){ int t; scanf("%d", &t); while (t --) { flag = 0; todo = 0; memset(row, false , sizeof(row)); memset(col, false , sizeof(col)); memset(blo, false , sizeof(blo)); for (int i = 1; i <= 9; ++ i) { scanf("%s", square[i]+1); for (int j = 1; j <= 9; ++ j) { if (square[i][j] == '0') { x[todo] = i; y[todo] = j; todo ++; } else { row[i][square[i][j]-'0'] = 1; col[j][square[i][j]-'0'] = 1; blo[block(i,j)][square[i][j]-'0'] = 1; } } } dfs(0); for (int i = 1; i <= 9; ++ i) printf("%s\n", square[i]+1); }}结果:Accepted 0.35s
剪枝后代码:
#include <cstring>#include <cstdio>#include <algorithm>using namespace std;char square[10][10];bool row[10][10], col[10][10], blo[10][10];int todo, flag;int block(int i, int j) {return (i-1)/3*3 + (j-1)/3 + 1;}struct TODO{int x, y, b, pNum;TODO() {}TODO(int _x, int _y): x(_x), y(_y), b(block(_x,_y)), pNum() {}void calc(){for (int i = 1; i <= 9; ++ i)if (!row[x][i] && !col[y][i] && !blo[b][i])pNum ++;}};bool cmp(const TODO &a, const TODO &b) {return a.pNum < b.pNum;}TODO p[85];void dfs(int n){if (flag || n == todo) { flag = 1; return; }int xx = p[n].x, yy = p[n].y, bl = p[n].b;for (int temp = 1; temp <= 9; ++ temp){if (!row[xx][temp] && !col[yy][temp] && !blo[bl][temp]){square[xx][yy] = temp+'0';row[xx][temp] = 1; col[yy][temp] = 1; blo[bl][temp] = 1;dfs(n+1); if (flag) return;row[xx][temp] = 0; col[yy][temp] = 0; blo[bl][temp] = 0;}}}int main(){int t;scanf("%d", &t);while (t --){flag = 0; todo = 0;memset(row, false , sizeof(row));memset(col, false , sizeof(col));memset(blo, false , sizeof(blo));for (int i = 1; i <= 9; ++ i){scanf("%s", square[i]+1);for (int j = 1; j <= 9; ++ j){if (square[i][j] == '0')p[todo++] = TODO(i,j);else{row[i][square[i][j]-'0'] = 1;col[j][square[i][j]-'0'] = 1;blo[block(i,j)][square[i][j]-'0'] = 1;}}}for (int i = 0; i < todo; ++ i) p[i].calc();sort(p, p+todo, cmp);dfs(0);for (int i = 1; i <= 9; ++ i)printf("%s\n", square[i]+1);}}结果:Accepted 0.02s
1317剪枝前代码:
#include <cstring>#include <cstdio>#define N 15char square[N][N];bool row[N][N], col[N][N], blo[N][N];int x[85], y[85], ans[N][N], todo, num;inline int block(int i, int j) {return (i-1)/3*3 + (j-1)/3 + 1;}void dfs(int n){ if (n == todo) { num ++; if (num == 1) for (int i = 1; i <= 9; ++ i) for (int j = 1; j <= 9; ++ j) ans[i][j] = square[i][j]-'0'; return; } int xx = x[n], yy = y[n], bl = block(xx,yy); for (int temp = 1; temp <= 9; ++ temp) { if (!row[xx][temp] && !col[yy][temp] && !blo[bl][temp]) { square[xx][yy] = temp+'0'; row[xx][temp] = 1; col[yy][temp] = 1; blo[bl][temp] = 1; dfs(n+1); row[xx][temp] = 0; col[yy][temp] = 0; blo[bl][temp] = 0; } }}int main(){ int t; scanf("%d", &t); for (int Case = 1; Case <= t; ++ Case) { if (Case != 1) printf("\n"); num = 0; todo = 0; memset(row, false , sizeof(row)); memset(col, false , sizeof(col)); memset(blo, false , sizeof(blo)); for (int i = 1; i <= 9; ++ i) { scanf("%s", square[i]+1); for (int j = 1; j <= 9; ++ j) { if (square[i][j] == '_') { x[todo] = i; y[todo] = j; todo += 1; } else { row[i][square[i][j]-'0'] = 1; col[j][square[i][j]-'0'] = 1; blo[block(i,j)][square[i][j]-'0'] = 1; } } } dfs(0); if (num == 0) printf("Puzzle %d has no solution\n", Case); else if (num == 1) { printf("Puzzle %d solution is\n", Case); for (int i = 1; i <= 9; ++ i) { for (int j = 1; j <= 9; ++ j) printf("%d", ans[i][j]); printf("\n"); } } else printf("Puzzle %d has %d solutions\n", Case, num); }}结果:Time Limit Exceeded
剪枝后代码:
#include <cstring>#include <cstdio>#include <algorithm>using namespace std;#define N 12char square[N][N], ans[N][N];bool row[N][N], col[N][N], blo[N][N];int todo, num;int block(int i, int j) {return (i-1)/3*3 + (j-1)/3 + 1;}struct TODO{int x, y, b, pNum;TODO() {}TODO(int _x, int _y): x(_x), y(_y), b(block(_x,_y)), pNum(0) {}void calc(){for (int i = 1; i <= 9; ++ i)if (!row[x][i] && !col[y][i] && !blo[b][i])pNum ++;}};bool cmp(const TODO &a, const TODO &b) {return a.pNum < b.pNum;}TODO p[85];void dfs(int n){if (n == todo){num ++;if (num == 1) memcpy(ans, square, sizeof(square));return;}int xx = p[n].x, yy = p[n].y, bl = p[n].b;for (int temp = 1; temp <= 9; ++ temp){if (!row[xx][temp] && !col[yy][temp] && !blo[bl][temp]){square[xx][yy] = temp+'0';row[xx][temp] = 1; col[yy][temp] = 1; blo[bl][temp] = 1;dfs(n+1);row[xx][temp] = 0; col[yy][temp] = 0; blo[bl][temp] = 0;}}}int main(){int t;scanf("%d", &t);for (int Case = 1; Case <= t; ++ Case){if (Case != 1) printf("\n");num = 0; todo = 0;memset(row, false , sizeof(row));memset(col, false , sizeof(col));memset(blo, false , sizeof(blo));for (int i = 1; i <= 9; ++ i){scanf("%s", square[i]+1);for (int j = 1; j <= 9; ++ j){if (square[i][j] == '_')p[todo++] = TODO(i,j);else{row[i][square[i][j]-'0'] = 1;col[j][square[i][j]-'0'] = 1;blo[block(i,j)][square[i][j]-'0'] = 1;}}}for (int i = 0; i < todo; ++ i) p[i].calc();sort(p, p+todo, cmp);dfs(0);if (num == 0) printf("Puzzle %d has no solution\n", Case);else if (num == 1){printf("Puzzle %d solution is\n", Case);for (int i = 1; i <= 9; ++ i)printf("%s\n", ans[i]+1);}else printf("Puzzle %d has %d solutions\n", Case, num);}}结果:Accepted 0.3s
- soj 1162. Sudoku[Special judge] 1317. Sudoku
- soj 1664. Su-Su-Sudoku
- soj dsa extra 1002 sudoku
- Sudoku
- sudoku
- Sudoku
- sudoku
- Sudoku
- Sudoku
- sudoku
- sudoku
- Sudoku
- Sudoku
- Sudoku
- Sudoku
- Sudoku
- Sudoku
- Sudoku
- 关于servlet和jsp路径表达方式的不同
- set intersection问题求解(python版)
- android in practice_Preparing for configuration changes(MyMovies project)
- hdu 2492
- 基于jQuery的一个简单聊天室
- soj 1162. Sudoku[Special judge] 1317. Sudoku
- 解决lein在Administrator目录的方法
- without base relocation /fixed:no
- Keil中预定义的字符串
- 黑马程序员-关于java中变量的总结
- 运动估计与运动补偿
- GPS协议
- java基础方面种种问答
- Android常用控件--EditText