c语言编程:优化回溯解数独程序
2012-07-22 17:49
411 查看
上次在博客上发了一篇《C语言:回溯解数独程序》。实在很粗糙,效率相当差。正如在群里一位朋友说的:
你能不能别像傻瓜式一样从左到右从上到下这样搜索呢?如果你这样,我出第一行是空的数独题,那你不就要算死了?
听了这话也怪不好意思的,而且他确实给了我下面这么一个题目(是无解的),但我的题目却是卡住很久都没算出来。
这样之后,代码的效率的确高了。上面的那个题目我统计了一下时间是这个多(采用clock()函数):
然后我又找了几个题目来算,时间也减少了很多,下面举一个例,题目是:
下面是结果:
我知道这个解法还有一定的缺陷,因为对回溯的不熟悉,我不是很清楚findposition还可以怎样优化。但是我知道优化的方法还有很多,所以这篇文章是(一)。
下面再说下对上次程序的小改动:
init函数应该检查输入是否合法,就是检查一行或一列或一个3*3小九宫格是不是有相同的数字,这个很简单,改动后的代码如下:
还有readFile函数可以这样改,简洁很多(也是上面那个网友说的,谢谢了)
最后我想说的是今天群里有位朋友说我的博客太丑了,而且也不更新。他搜索site:www.dabentu.com搜不出,于是说博客太丑了百度都不收录 的。我马上搜了一下site:dabentu.com。有120多条,马上截图过去。虽然我不是很清楚这方面的事,但我也知道dabentu.com才是 顶级域名。自己选择这款主题就是因为喜欢,我也不在乎他人评价好坏,而且博客不收录没访问也没关系,我只是用来记录自己的学习经历,用来上传自己的一些代 码而已。说我不更新的话,确实,好几天没更新了。这几天一直不知道有什么好写的,觉得就算写了对别人也没太大价值,就不去费那个时间了。
好了,这就是这篇文章的内容(全文完)
转载自大笨兔http://dabentu.com
你能不能别像傻瓜式一样从左到右从上到下这样搜索呢?如果你这样,我出第一行是空的数独题,那你不就要算死了?
听了这话也怪不好意思的,而且他确实给了我下面这么一个题目(是无解的),但我的题目却是卡住很久都没算出来。
[code lang="js"] 0000004900 0000000000 0000000000 0007090000 0080000000 0000607000 1005300002 00000048000 原本再设计程序的时候findPosition函数是找出目前数字相对密集的位置,因为从这里开始计算量是最少的,但是由于当时并没有什么好的实现方法,自己又想早点将数独程序解出来,就采用上面说的最傻瓜的从上面第一个空位置开始。如果是一个正常的题目的话解题时间还能接受,但是如果像他给我这个无解的题目的话就不行了。所以我想还是只有先将findPosition优化一下,找出数字相对密集的地方。优化后的代码如下: [code lang = "js"] void findPosition(int *line,int *row) { int maxnum,maxrow; int i,j; maxnum = maxrow = -1; // //找到已填好数字最多的一行 for(i = 1;i < 10;i++){ if(9 == sd.line_count[i]) continue; if(sd.line_count[i] > maxnum){ maxnum = sd.line_count[i]; *line = i; } } //找到那一行没有填数且列填好数字最多的位置 for(i = 1;i < 10;i++){ if(0 == sd.data[*line][i]){ if(sd.row_count[i] > maxrow){ maxrow = sd.row_count[i]; *row = i; } } } }
这样之后,代码的效率的确高了。上面的那个题目我统计了一下时间是这个多(采用clock()函数):
[code lang="js"] test.txt We don't find an answer. It cost 0.010000s.
然后我又找了几个题目来算,时间也减少了很多,下面举一个例,题目是:
[code lang="js"] 0 6 1 0 3 0 0 2 0 0 5 0 0 0 8 1 0 7 0 0 0 0 0 7 0 3 4 0 0 9 0 0 6 0 7 8 0 0 3 2 0 9 5 0 0 5 7 0 3 0 0 9 0 0 1 9 0 7 0 0 0 0 0 8 0 2 4 0 0 0 6 0 0 4 0 0 1 0 2 5 0
下面是结果:
[code lang="js"] c:\\test.txt We find an answer. 7 6 1 9 3 4 8 2 5 3 5 4 6 2 8 1 9 7 9 2 8 1 5 7 6 3 4 2 1 9 5 4 6 3 7 8 4 8 3 2 7 9 5 1 6 5 7 6 3 8 1 9 4 2 1 9 5 7 6 2 4 8 3 8 3 2 4 9 5 7 6 1 6 4 7 8 1 3 2 5 9 We find an answer. It cost 0.000000s.
我知道这个解法还有一定的缺陷,因为对回溯的不熟悉,我不是很清楚findposition还可以怎样优化。但是我知道优化的方法还有很多,所以这篇文章是(一)。
下面再说下对上次程序的小改动:
init函数应该检查输入是否合法,就是检查一行或一列或一个3*3小九宫格是不是有相同的数字,这个很简单,改动后的代码如下:
[code lang="js"] //把从文件中读取的数字保存进题目信息 int initSodu(int a[81],psodu ps) { if(NULL == ps) return 0; int i,line,row; for(i = 0;line = (i/9 + 1),row = (i % 9 + 1),i < 81;i++){ if((ps->data[line][row] = a[i]) != 0){//该位置已填数字才有信息读啊 if(testThisNumber(line,row,a[i])) return 0; ps->line_number[line][a[i]] = 1; ps->row_number[row][a[i]] = 1; ps->small_number[TOSMALL(line,row)][a[i]] = 1; ps->line_count[line]++; ps->row_count[row]++; ps->small_count[TOSMALL(line,row)]++; ps->achieve_number++; } } return 1; }
还有readFile函数可以这样改,简洁很多(也是上面那个网友说的,谢谢了)
[code lang="js"] //从文件中读取数独题目 int readFile(char *filename,int a[]) { FILE *fp = NULL; int i = 0; char c; //文件是否成功打开 if((fp = fopen(filename,"r")) != NULL){ //从文件中读取数字,读到文件尾 while((c = fgetc(fp)) != EOF){ if(c >= '0' && c <= '9' && i < 81) a[i++] = c - '0'; } fclose(fp); //关闭文件 } else return 0; //文件读取失败则返回 if(i != 81) return 0; return 1; //文件读取成功 }
最后我想说的是今天群里有位朋友说我的博客太丑了,而且也不更新。他搜索site:www.dabentu.com搜不出,于是说博客太丑了百度都不收录 的。我马上搜了一下site:dabentu.com。有120多条,马上截图过去。虽然我不是很清楚这方面的事,但我也知道dabentu.com才是 顶级域名。自己选择这款主题就是因为喜欢,我也不在乎他人评价好坏,而且博客不收录没访问也没关系,我只是用来记录自己的学习经历,用来上传自己的一些代 码而已。说我不更新的话,确实,好几天没更新了。这几天一直不知道有什么好写的,觉得就算写了对别人也没太大价值,就不去费那个时间了。
好了,这就是这篇文章的内容(全文完)
转载自大笨兔http://dabentu.com
相关文章推荐
- 数独C语言编程-正推与回溯
- c语言:回溯解数独程序
- ADI Blackfin处理器的C语言编程与优化——内存Memory和Cache优化
- socket编程之C语言一个简单监听程序
- C语言编程优化运行速度
- linux网络编程:用C语言实现的聊天程序(同步通信)
- C语言:编程练习参考程序
- linux下C语言编程1-gdb调试程序简介
- C语言编程程序的内存如何布局
- linux网络编程:用C语言实现的聊天程序(异步通信)
- c语言:2种方法编程及优化;喝汽水问题
- C语言实例编程:回溯法计算总费用最小费用
- C语言 递归(回溯) 解决数独问题
- c语言编程---性能优化
- C语言编程程序的内存如何布局
- C语言小程序:Windows窗口游戏编程模板
- 数组比特【编程珠玑】如何优化程序打印出小于100000的素数
- 搞定linux上MySQL编程(六):C语言编写MySQL程序(结)
- C语言编程-----程序的内存布局
- linux网络编程:用C语言实现的聊天程序(同步通信)