相邻两方格内的两个整数之和为质数-经典算法详解
来源:互联网 发布:2015手机淘宝最新版 编辑:程序博客网 时间:2024/05/21 09:51
为什么要详解?主要是因为我自己看的时候都花了很长时间才明白。
题目:
在9(3 x 3)个方格的方阵中填入数字1到N(N>=10)内的9个数字,使所有相邻两方格内的两个整数之和为质数(素数),试求出所有满足要求的数字填充方案。
先画图:(3*3表格)
0
1
2
3
4
5
6
7
8
由于一维数组更好处理,所以变换成一维数组
a[10]:
0
1
2
3
4
5
6
7
8
9
数据结构 1)
int checkM[9][3]={{-1},{0,-1},{1,-1},
{0,-1},{1,3,-1},{2,4,-1},
{3,-1},{4,6,-1},{5,7,-1}};
这是干什么用的呢?
要是相邻方格的数字之和为质数,我们约定试探的时候按照[1…N]的顺序来试探。
这样的话,0号方格不需要和任何单元格匹配,因为他是第一个,所以checkM[0]={-1,0,0};
这说明a[0]不需要任何试探
再看i=1的时候
单元格1和0相邻,所以在单元格1中填入数字的时候要与0号格内的数字之和为质数。
所以checkM[1] = {0,-1,0}; 【注】匹配的时候看到-1就不会继续向下走了。
在看i=4的时候
格4和格1,3,5,7相邻,但是由于我们约定了顺序,只需验证1,3是否合格即可,所以checkM[4]={1,3,-1};
……
上图易于理解:
0
1
2
3
4
5
6
7
8
0
1
2
0
-1
1
0
-1
2
1
-1
3
0
-1
4
1
3
-1
5
2
4
-1
6
3
-1
7
4
6
-1
8
5
7
-1
数据结构 2)
b[N]
里面装着N个数字[1…N],如果哪个数字被选中拿到矩阵中去,那么就把它从数组b中清除(置零),下次就不会重复选择。如果不用了再置一。
程序段 1)
int selectNum(int start)
{ int j;
for(j=start;j<=N;j++)
if(b[j]!=0)return j;
return0;
}
从start开始选择以前没有被选过的数字
程序段 2)
int check(int pos)
{ int i;
if(pos<0) return 0;
i=0;
while(checkM[pos][i]!=-1 )
{ if(!isPrime( a[pos]+a[ checkM[pos][i] ] ) ) return 0;
i++;
}
return1;
}
判断新选择的数字是否符合标准(和为质数)
While循环就是不断的判断a[pos]+a[checkM[pos][i] ] 是否是质数。这样的好处就是在程序中省去了路径的判断,都则还要在程序中写
if(i-1 >= 0)
{
//try {...}
}
if(i+1 < N)
{
}
if(j-1 >= 0)
{
}
if(j+1 < N)
{
}
来判断4个方向。
程序段 3)
int extend(int pos)
{ a[++pos]=selectNum(1);
b[a[pos] ] = 0;
returnpos;
}
如果当前a[pos]的值满足质数条件,那么该数字放置成功,下面是试探下一个pos。
a[++pos]=selectNum(1); 为下一个路径寻找可行的数字。
b[ a[pos] ] = 0; 将找到数字的可用性置零,即该数已经被引用,不能再选择了。
程序段4)
int change(int pos)
{ int j;
while(pos>=0 && (j=selectNum( a[pos]+1 )) == 0)
b[a[pos--] ] = 1;
if(pos < 0 ) return -1;
b[a[pos] ] = 1;
a[pos]= j;
b[j] =0;
returnpos;
}
当一条路走不通,或者该路径的pos==8即该路径已经走完时,选择另一条合适的路径继续试探。
下面是pos == 8 的情况详解:
1. j=selectNum(a[pos]+1 ) ,对于pos==8寻找下一个可行的数字。
2. 如果找不到,即j==0,那么b[ a[pos] ] = 1; 将这个数字退还给b数组,pos--,去试探pos==7是否还有可行的情况。
3. if(pos < 0 ) return -1; 如果都试探过了,那么返回结束。
4. 否则
4.1 将原来a[pos]中的数据退还给数组b
4.2 将a[pos]中的数据置为j(即刚寻到的一个新数据)
4.3 将j在b数组中的位置置零,表示已经被引用
程序段5)
void find()
{ int ok=1, pos=0;
a[pos]=1; b[ a[pos] ]=0;
do
{
if(ok ) {
if(pos == 8 )
{
write(a);
pos= change(pos);
}else {
pos= extend(pos);
}
}
else
pos= change(pos);
ok= check(pos);
//printf("test %d %d%d/n",ok,pos,a[pos]);write(a);(void)getchar();
}while(pos >= 0);
}
这是整体框架
懂了上面的,这个就不难了。
完整代码:
- 相邻两方格内的两个整数之和为质数-经典算法详解
- 关于相邻两数之和为素数的解答
- 300-500内的质数(素数)个数和前10个最大的质数之和算法
- 巧排数字,将1,2,...,19,20这20个数字排成一排,使得相邻的两个数字之和为一个素数,且首尾两数字之和也为一个素数。编程打印出所有的排法。
- 将1、2、...、20这20个数排成一排,使得相邻的两个数之和为一个素数,且首尾两数字之和也为一个素数。
- python实现整数分解为质数的算法
- 算法爱好者——判断某整数是否为两数平方之和 ? 待解决
- (hdu step 4.3.2)Prime Ring Problem(n个数成环,输出两两之和为质数的所有情况)
- 求从一个整数数组中两个数之和为m的两个数
- hdu 1016 深搜加步长 相邻两个元素为质数建立边
- 整数分解为质数的乘积
- XYNUOJ 两个整数之和
- 求两个整数之和
- 两个整数之和
- 判断某整数是否为两数平方之和
- 从1到20个数字排成一圈,每两个相邻数字之和为一个素数
- 经典题:一个整数分解为连续正整数之和
- 验证4-100内所有偶数可以写成两个质数之和
- (转)
- (转)
- ORACLE权限关于with admin option和with grant
- Android学习指南
- 如何设置快速的debian源
- 相邻两方格内的两个整数之和为质数-经典算法详解
- Hadoop源代码的边角料:HDFS的数据通信机制
- ubuntu文本界面乱码解决方法
- c# 处理正则表达式
- 使用DirectInput进行交互
- c中的eof
- linux(ubuntu)下架设FTP(vsftpd)服务器
- HOWTO: Create and submit your first Linux kernel patch using GIT
- linux下关闭xenbr,virbr服务