四阶素数幻方问题

本文介绍了一种使用递归搜索算法解决特定数学问题的方法——构造一个四阶幻方,其中任意相邻数字之和均为素数。提供了C和VB两种语言的实现代码,并列举了部分解决方案。

用1到16构成一个四阶幻方,要求任意相邻两个方格中的数字之各均为素数?

(原帖见:http://topic.youkuaiyun.com/u/20070830/18/1f1957c1-5e66-4c3b-8883-d7eef64c8da1.html)

NowCan 网友的解法:

直接递归搜,4阶很快的。以下这个程序就是这样的思路,结果未经过验证。

/*
将1-N^2这N^2个数添如N*N的方格中,每个方格填一个整数,使所有相邻两个方格内的两个整数之和为质数。
例如N=3时如下,无解。N=4时,2992解?N=5时,917848解?算了半个小时
A0A1A2
A3A4A5
A6A7A8
PRIME(A0+A1)
PRIME(A0+A3)
PRIME(A1+A2)
PRIME(A1+A4)
PRIME(A2+A5)
PRIME(A3+A4)
PRIME(A3+A6)
PRIME(A4+A5)
PRIME(A4+A7)
PRIME(A5+A8)
PRIME(A6+A7)
PRIME(A7+A8)
*/
#include <stdio.h >
#include <math.h >
#include <windows.h >

#defineMAX_NUM30
#define_PRINT_0

unsignedlongResult[MAX_NUM*MAX_NUM],ResultNum,Used[MAX_NUM*MAX_NUM]={0};
boolPrimeTable[MAX_NUM*MAX_NUM*2]={false};
unsignedlongN,QN;

/**/
voidCreatePrimeTable(void)
{
PrimeTable[0]=false;
PrimeTable[1]=false;
PrimeTable[2]=true;
PrimeTable[3]=true;
for(unsignedlongj=5;j <=MAX_NUM*MAX_NUM*2;j+=2)
{
PrimeTable[j]=true;
for(unsignedlongi=3;i <=sqrt((double)j);i+=2)
{
if(j%i==0)
{
PrimeTable[j]=false;
break;
}
}
}
}

/**/
inlineboolIsPrime(unsignedlongn)
{
returnPrimeTable[n];
}

/**/
boolCheckIt(unsignedlongDeep)
{
if(Deep==0)
{
returntrue;
}
elseif(Deep <N)
{
returnIsPrime(Result[Deep]+Result[Deep-1]);
}
elseif(Deep%N==0)
{
returnIsPrime(Result[Deep]+Result[Deep-N]);
}
else
{
return(IsPrime(Result[Deep]+Result[Deep-1])&&IsPrime(Result[Deep]+Result[Deep-N]));
}
}

/**/
voidgo(unsignedlongDeep)
{
if(Deep==QN)
{
ResultNum++;
#if(_PRINT_)
printf("Findit!No.%lu\n",ResultNum);
for(unsignedlongi=0;i <QN;i++)
{
printf("%lu\t",Result[i]);
if(i%N==N-1)
{
printf("\n");
}
}

#else
printf("\rFind:%lu",ResultNum);
#endif
}
else
{
for(unsignedlongi=1;i <=QN;++i)
{
if(!Used[i])
{
Result[Deep]=i;
if(CheckIt(Deep))
{
Used[i]=1;
go(Deep+1);
Used[i]=0;
}
}
}
}
}

/**/
intmain(void)
{
DWORDtim;
ResultNum=0;
printf("InputN:");
scanf("%lu",&N);
QN=N*N;
tim=GetTickCount();
CreatePrimeTable();
go(0);
printf("\n\nN=%lu\n",N);
printf("Total=%lu\n",ResultNum);
printf("Time=%lu\n",GetTickCount()-tim);
return0;
}

几乎未加任何处理,转成VB代码如下:

Dim prime() As Byte, result() As Long, used() As Byte, n As Long, resultcount As Long
Function checkit(ByVal level As Long) As Byte
If level = 0 Then checkit = 1: Exit Function
If level < n Then checkit = prime(result(level) + result(level - 1)): Exit Function
If level Mod n = 0 Then checkit = prime(result(level) + result(level - n)): Exit Function
checkit = prime(result(level) + result(level - 1)) * prime(result(level) + result(level - n))
End Function

Sub run(Optional ByVal level As Long = 0)
Dim i As Long, j As Long
If level = n * n Then
resultcount = resultcount + 1
Debug.Print "No." & resultcount & vbCrLf & String(4 * n, "-")

For i = 0 To n - 1
For j = 0 To n - 1
Debug.Print Left(result(i * n + j) & " ", 4);
Next
Debug.Print
Debug.Print
Next
Else
For i = 1 To n * n
If used(i) = 0 Then
result(level) = i
If checkit(level) = 1 Then
used(i) = 1
run level + 1
used(i) = 0
End If
End If
Next
End If
Close #1
End Sub

Sub main()
Dim i As Long, tt As Double
n = 4
ReDim prime(n * n * 2)
ReDim result(n * n)
ReDim used(n * n)
ReDim s(1 To 1000000)
prime(2) = 1
prime(3) = 1
For i = 5 To 2 * n * n Step 2
For j = 3 To Int(Sqr(i))
If i Mod j = 0 Then Exit For
Next
If j = Int(Sqr(i)) + 1 Then prime(i) = 1
Next
tt = Timer
run
MsgBox "共找到" & resultcount & "组解,用时" & Timer - tt & "秒钟!"
End Sub

返回:

No.1
----------------
1 2 11 12

4 9 8 5

7 10 3 14

6 13 16 15

No.2
----------------
1 2 11 12

4 9 8 5

13 10 3 14

6 7 16 15

No.3
----------------
1 2 11 12

4 15 8 5

7 16 3 14

6 13 10 9

No.4
----------------
1 2 11 12

4 15 8 5

13 16 3 14

6 7 10 9

No.5
----------------
1 2 11 12

10 3 8 5

7 16 15 14

6 13 4 9

No.6
----------------
1 2 11 12

10 3 8 5

13 16 15 14

6 7 4 9

No.7
----------------
1 2 11 12

10 9 8 5

7 4 3 14

6 13 16 15

No.8
----------------
1 2 11 12

10 9 8 5

7 4 15 14

6 13 16 3

No.9
----------------
1 2 11 12

10 9 8 5

13 4 3 14

6 7 16 15

No.10
----------------
1 2 11 12

10 9 8 5

13 4 15 14

6 7 16 3

No.11
----------------
1 2 11 12

16 3 8 5

7 10 9 14

6 13 4 15

No.12
----------------
1 2 11 12

16 3 8 5

13 10 9 14

6 7 4 15

No.13
----------------
1 2 11 12

16 15 8 5

7 4 3 14

6 13 10 9

No.14
----------------
1 2 11 12

16 15 8 5

7 4 9 14

6 13 10 3

No.15
----------------
1 2 11 12

16 15 8 5

13 4 3 14

6 7 10 9

No.16
----------------
1 2 11 12

16 15 8 5

13 4 9 14

6 7 10 3

.......

共计2992组解法

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值