问题描述:把整数{1,2,…,n}填写到一个环中,要求每个数只填写一次,并且相邻两数之和为素数。
约束条件:
1.与已经填写到素数环中的整数不重复;
2.与前面相邻的整数之和是素数;
3.最后一个填写的整数与第一个填写的整数之和为素数。
在填写第k个整数时,如果满足上述约束条件,则继续填写第k+1个位置;如果1~n个数都无法填写到第k个位置,则取消对第k个位置的填写,回溯到第k-1个位置。
完整代码(实现一):
#include<stdio.h>
#include<math.h>
typedef struct Node
{
int index; //当前处理数据索引
int next; //下一个节点的遍历进度
}Node;
int judge(int x) //素数判断
{
for(int i=2;i<=sqrt(x);i++)
{
if(x%i==0)
return 0;
}
return 1;
}
void pr()
{
int n;
printf("请输入环大小:");
scanf("%d",&n);
int a[n]; //存储数据
bool visited[n]; //对已插入数进行标记
for(int i=0;i<n;i++)
{
a[i]=i+1;
visited[i]=false;
}
Node t[n]; //计算过程中的产生的节点
int count=0;
t[count++].index=0;
t[count-1].next=0;
visited[0]=true;
while(count>0&&count!=n)
{
int flag=0; //插入成功与否标记
int start=t[count-1].next; //避免回溯过程中重复访问已遍历过的值,next记录了上一次访问到的地方
for(int j=start;j<n;j++)
{
if(!visited[j]&&judge(a[t[count-1].index]+a[j]))
{
if(count==n-1)
{
if(!judge(a[j]+a[t[0].index])) //添加对最后一个整数的约束条件,即最后一个整数与第一个整数之和为素数
break;
}
flag=1;
t[count++].index=j; //插入数据
t[count-1].next=0;
t[count-2].next=j+1;
visited[j]=true;
break;
}
}
if(flag==0) //插入失败,回溯
{
visited[t[count-1].index]=false;
count--;
}
}
if(count==n)
{
for(int i=0;i<count;i++)
printf("%d ",a[t[i].index]);
}
else
printf("无解");
}
main()
{
pr();
}
该实现需要对待填写数据进行存储,空间复杂度较高,实现二将很好的利用待填写数据的特点降低空间复杂度。
完整代码(实现二) :
#include<stdio.h>
#include<math.h>
int judge(int x) //素数判断
{
for(int i=2;i<=sqrt(x);i++)
if(x%i==0)
return 0;
return 1;
}
void pr()
{
int n;
printf("请输入环大小:");
scanf("%d",&n);
int a[n];
bool visited[n+1]; //为插好的数字标记
for(int j=0;j<n+1;j++)
visited[j]=false;
for(int i=0;i<n;i++)
a[i]=1;
int k=1;
visited[1]=true;
while(k>=0)
{
a[k]=a[k]+1;
while(a[k]<=n) //往相依位置插数字
{
if(!visited[a[k]]&&judge(a[k]+a[k-1]))
{
break;
}
else
{
a[k]++;
}
}
if(a[k]<=n)
{
if(k==n-1&&judge(a[k]+a[0])) //最后一个数字与第一个数字之和进行验证
{
break;
}
else if(k<n-1)
{
visited[a[k]]=true;
k++;
}
else if(k==n-1) //最后一个数字插入失败,回溯
{
a[k]=1;
k--;
visited[a[k]]=false;
}
}
else
{
a[k]=1; //插入失败
k--;
visited[a[k]]=false;
}
}
if(k<0)
printf("无解\n");
else
{
printf("满足条件的一个序列为:");
for(int i=0;i<n;i++)
printf("%d ",a[i]);
}
}
main()
{
pr();
}
运行结果: