用代码证明自己闲的蛋疼(三)——回溯法做数独
2016-11-24 11:20
274 查看
数独大家应该都玩过,1~9数字,满足每一行、每一列、每一个粗线宫(3*3)内的数字均含1-9,不重复。
起始会有一些给定的值,然后我们去填剩余的数,一个合理的数独最终解一定是唯一的。
九日哥也很喜欢玩数独,喜欢到最后都懒得算了,直接写个程序搜出答案。。。
解决思路是回溯,如果对回溯不了解的同学可以移步 http://blog.csdn.net/sm9sun/article/details/53244484
其实想一想,数独的规则是不是跟N皇后很相似??
我们假设一个9X9的二维数组a[9][9],如何判断值k是否可以插入某个点a[i][j]呢?
①该数组所有横向没有存在过k值
for(n=0;n<9;n++)
if(a[i]
==k)return 0;
②该数组纵向没有存在过k值
for(m=0;m<9;m++)
if(a[m][j]==k)return 0;
③该点位于的九宫格3X3区间没有存在过k值
xm=(i/3)*3,xn=(j/3)*3;
for(m=xm;m<xm+3;m++)
for(n=xn;n<xn+3;n++)
if(a[m]
==k)return 0;
再来看看搜索的过程,9X9总共81个格子,我们以一个数字n作为标记i,j坐标点的变量(i=n/9; j=n%9;)
即:80就相当于最后一个格子 8/9=8,8%9=8(数组以0开始)
如果n等于80,那么就表示我已经遍历到最后一个点了,如果满足条件的话我们就找到最终解了。
如果n不等于80,表示我们还要继续往下试,即用不同的k值试探当前i,j点是否可以放下
回归后回溯即可~
完整代码如下:
起始会有一些给定的值,然后我们去填剩余的数,一个合理的数独最终解一定是唯一的。
九日哥也很喜欢玩数独,喜欢到最后都懒得算了,直接写个程序搜出答案。。。
解决思路是回溯,如果对回溯不了解的同学可以移步 http://blog.csdn.net/sm9sun/article/details/53244484
其实想一想,数独的规则是不是跟N皇后很相似??
我们假设一个9X9的二维数组a[9][9],如何判断值k是否可以插入某个点a[i][j]呢?
①该数组所有横向没有存在过k值
for(n=0;n<9;n++)
if(a[i]
==k)return 0;
②该数组纵向没有存在过k值
for(m=0;m<9;m++)
if(a[m][j]==k)return 0;
③该点位于的九宫格3X3区间没有存在过k值
xm=(i/3)*3,xn=(j/3)*3;
for(m=xm;m<xm+3;m++)
for(n=xn;n<xn+3;n++)
if(a[m]
==k)return 0;
再来看看搜索的过程,9X9总共81个格子,我们以一个数字n作为标记i,j坐标点的变量(i=n/9; j=n%9;)
即:80就相当于最后一个格子 8/9=8,8%9=8(数组以0开始)
如果n等于80,那么就表示我已经遍历到最后一个点了,如果满足条件的话我们就找到最终解了。
如果n不等于80,表示我们还要继续往下试,即用不同的k值试探当前i,j点是否可以放下
回归后回溯即可~
void SD(int a[9][9],int n)//求解 { int i,j; int b[9][9]; for(i=0;i<9;i++) for(j=0;j<9;j++) b[i][j]=a[i][j]; //用b进行尝试 i=n/9; j=n%9; //行列 if(a[i][j]!=0) //如果该位置固定 (n==80)?print(b):SD(b,n+1); else { int k; //试数 for(k=1;k<=9;k++) if(test(b,i,j,k)) //可以 { b[i][j]=k; n==80?print(b):SD(b,n+1); b[i][j]=0; //回溯 } } }
完整代码如下:
#include<stdio.h>
int count=0;
void print(int a[9][9])
{
count++;
printf("case: %d:\n",count);
for(int i=0;i<9;i++)
for(int j=0;j<9;j++)
{
printf("%d",a[i][j]);
j==2?printf(" "):0;
j==5?printf(" "):0;
j==8?printf("\n"):0;
j==8&&i%3==2?printf("\n"):0;
}
}
//判断是
4000
否可以将第i行、第j列的数设为k
int test(int a[9][9],int i,int j,int k)
{
int m,n,xm,xn;
for(n=0;n<9;n++)
if(a[i]
==k)return 0;
for(m=0;m<9;m++)
if(a[m][j]==k)return 0;
xm=(i/3)*3,xn=(j/3)*3;
for(m=xm;m<xm+3;m++)
for(n=xn;n<xn+3;n++)
if(a[m]
==k)return 0;
return 1;
}
void SD(int a[9][9],int n)//求解 { int i,j; int b[9][9]; for(i=0;i<9;i++) for(j=0;j<9;j++) b[i][j]=a[i][j]; //用b进行尝试 i=n/9; j=n%9; //行列 if(a[i][j]!=0) //如果该位置固定 (n==80)?print(b):SD(b,n+1); else { int k; //试数 for(k=1;k<=9;k++) if(test(b,i,j,k)) //可以 { b[i][j]=k; n==80?print(b):SD(b,n+1); b[i][j]=0; //回溯 } } }
int main()
{
int a[9][9];
printf("请输入原始数据,没有数据用0代替。\n");
for(int i=0;i<9;i++)
for(int j=0;j<9;j++)
scanf("%d",&a[i][j]);
printf("-------------------\n\n");
SD(a,0);
if(count==0)
printf("此数独无解!");
return 0;
}
相关文章推荐
- 用代码证明自己闲的蛋疼(四)——简易坑爹版学生管理系统
- 用代码证明自己闲的蛋疼(一)——cmd闪瞎狗眼
- 回溯法求解数独问题的思路和代码
- VS2008 JS调试和Silverlight 后台代码调试 相互影响的问题。---自己做实例证明
- 【HDU4313】Matrix 多校 解题报告+AC代码+思路+算法正确性证明,此为Kruskal贪心恶心版本,非自虐倾向慎入!建议想找解题报告的童鞋看简单版本的,这个我写给自己【目标达成 0.2%】
- 自己实现的简单的Vector代码
- python学习第九章类部分课后练习自己尝试的代码
- android 调用自己写的C函数库 代码
- JAVA学习(十二)__关于JAVA代码里黄色警告线的注意方法(自己整理)
- Thinking in Java——自己手写的代码
- Ajax (部分二:prototype.js代码前半部)自己做的,总结页面向后台传Form值、单个值和后台向前台传一个或是一组值
- 在vs2008上编译自己的代码,总是出现句法差错
- iOS之侧滑返回无需第三方,只需在自己的BaseNavController添加大概20行代码即可
- 使用百度地图SDK来开发自己的程序(主要是考察自己读代码的能力)
- 实验 3.1.5 查看代码中各数据存储位置 示例程序: mem_add.c 1. 在自己的机器上运行示例程序。 2. 分析实验结果,图示程序运行时各数据位置。
- 并行计算思考----回溯法求解数独问题
- 自己OJT时的代码
- 自己写代码对比工具
- 回溯法求解数独(C++实现)
- Merge Two Sorted Lists,自己的代码一遍通过