数独

问题描述:
这个游戏只有一个规则:将格子填满使得, 每一行,每一列,和每一个小的九宫格恰好包含1-9 这9 个数字是由于规则简单而又变化多端,数独一时间风靡全球。
现在,我们希望你能编写一个程序解决数独问题。


输入数据

输入数据一共9 行,每行有9 个字符。
输入数据描述了一个待解决的数独,其中,“?”表示数独中的空缺。
我们的输入数据总保证有唯一解。


输出数据
输出一共9 行,每行9 个数字,表示你的答案。

样例输入
5????7??6
?6????5?4
?834?????
???182?4?
??1???9??
?7?369???
?????543?
1?5????9?
7??2????1

样例输出
514927386
967831524
283456179
659182743
321574968
478369215
892615437
135748692
746293851

 

这道题别想太多,爆搜就行。每一步找到一个是'?' 的的格子,然后尝试填入1到9,若成功填入,就递归找下一个'?' 的格子。

 

这道题的重点是在于判断这个格子是否能填这个数。

我们要判断这个数在该行,该列和该九宫格的合法性。因为数字只有1到9,所以开二维数组标记就行,vis[i][j] = 1代表在第 i 行(列)已经有数字 j 了。这样行和列的判断就完成了。

重点是九宫格的判断。他之所以不好表示,是因为这个格在哪个九宫格不仅跟他在那一列有关,还跟在哪一行有关。虽然说开三维数组就行,但是就是感觉有些白痴。所以这里我将它编码了一下。

  vis[ i / 3  * 10+ j / 3][x]  = 1 代表格子(i, j) 所在的九宫格有 x 这个数

这样编码,就能把81个格子分成9份了。如下图

 

刚开始我智障写成了vis[ i % 3  * 10+ j % 3][x],愣是没发现,然后就GG了。

 1 #include<cstdio>
 2 #include<algorithm>
 3 #include<cmath>
 4 #include<cstring>
 5 #include<iostream>
 6 using namespace std;
 7 typedef long long ll;
 8 #define rep(i, a, n) for(int i = a; i <= n; ++i)
 9 #define per(i, n, a) for(int i = n; i >= a; --i)
10 char a1[15][15];
11 int a[15][15];
12 bool hang[15][15], lie[15][15], kuai[1000][15];
13 int xx, yy;
14 void print() {
15     for(int i = 0; i < 9; ++i)
16     {
17         for(int j = 0; j < 9; ++j) printf("%d", a[i][j]);
18         printf("\n");
19     }
20     exit(0);        //这是个神奇的东西,就是直接停止程序 
21 }
22 bool search(int& xx, int& yy)
23 {
24     for(xx = 0 ; xx < 9; ++xx)
25         for(yy = 0; yy < 9; ++yy)
26             if(a[xx][yy] == 0) return true;
27     return false;
28 }
29 void dfs() 
30 {
31     if(search(xx, yy)) 
32     {
33         int newx = xx, newy = yy;
34         for(int i = 1; i <= 9; ++i)
35         {
36             if(!hang[newx][i] && !lie[newy][i] && !kuai[newx / 3 * 10 + newy / 3][i]) 
37             {
38                 hang[newx][i] = lie[newy][i] = kuai[newx / 3  * 10 + newy / 3][i] = 1;
39                 a[newx][newy] = i;
40                 dfs();
41                 hang[newx][i] = lie[newy][i] = kuai[newx / 3  * 10 + newy / 3][i] = 0;
42                 a[newx][newy] = 0;
43             }
44         }
45     }
46     else print();        //没有要填的数了 
47 }
48 int main() {
49     freopen("sudoku.in", "r", stdin);
50     freopen("sudoku.out", "w", stdout);
51     rep(i, 0, 8) scanf("%s", a1[i]);
52     rep(i, 0, 8)
53         rep(j, 0, 8)        //转化成整形数组,看的舒服
54         {
55             if(a1[i][j] == '?') a[i][j] = 0;        
56             else a[i][j] = a1[i][j] - '0';
57         }
58     rep(i, 0, 8)
59         rep(j, 0, 8) 
60             if(a[i][j])                         //因为数独中已经有些数了 
61                 hang[i][a[i][j]] = lie[j][a[i][j]] = kuai[i / 3 * 10 + j / 3][a[i][j]] = 1;
62     dfs();
63     return 0;
64 }

 

转载于:https://www.cnblogs.com/mrclr/p/8665920.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值