c++算法之回溯 素数环(二)
Description
输入正整数n,把整数1,2,3,…,n组成一个环,使得相邻两个整数之和均为素数。把全部的解按字典序排序后,从1开始编号,依次输出指定编号的k组解。最后一行输出总的方案数。同一个素数环只算一次。
Input
第1行:2个整数,n(n<=18)和k(1<=k<=10)
第2行:共有k个从小到大排列的整数,表示要输出的解的编号。
Output
前k行,每行一组解,对应于一个输入
第k+1行:一个整数,表示总的方案数。
Sample Input
10 4
1 2 5 8
Sample Output
1 2 3 4 7 6 5 8 9 10
1 2 3 4 7 10 9 8 5 6
1 2 3 8 5 6 7 10 9 4
1 2 3 10 9 8 5 6 7 4
96
分析:
算法思维与(一)一样,但需要注意这样两点(坑点):
1.“把全部的解按字典序排序后,从1开始编号,依次输出指定编号的k组解。最后一行输出总的方案数。同一个素数环只算一次。”实现这句话其实就是要固定环的第一个数为1,这样就可以保证不重复,且按字典序排序。
2.要求输出指定的k组解,我是在输出的时候处理的,要统计总数就在那里自增,再判断当前解是否是指定的k组解中的,是才输出
程序实现如下:
#include<cstdio>
#include<cmath>
int a[19],k,sum,n[11],num=1,q;
bool b[19]={0};
bool p(int s)//判断是否为素数
{
for(int i=2;i<=sqrt(s);i++)
if(s%i==0) return 0;
return 1;
}
void print()
{
sum++;//此时的sum也是此素数环的顺序,产生完所有的素数环之后,sum即为所有的组数
if(sum==n[num])//如果此时是k组数据,才输出
{
for(int i=1;i<q;i++)
printf("%d ",a[i]);
printf("%d\n",a[q]);
num++;//num滚动递增到下一个要求的素数环的序号
}
}
int search(int r)
{
for(int i=2;i<=q;i++)
if(!b[i]&&p(i+a[r-1]))//没有被使用过,且与前一个数相加是素数
{
a[r]=i;
b[i]=1;//保存并标记
if(r==q&&p(1+a[q])) print();//如果填完所有的数,且最后一个数与开头的数之和为素数
else search(r+1);//递归回溯
b[i]=0;
}
}
int main()
{
scanf("%d %d",&q,&k);
for(int i=1;i<=k;i++)
scanf("%d",&n[i]);//将k组数据保存在n数组中
a[1]=1;
b[1]=1;//将第一个数固定为1,从2开始搜索
search(2);
printf("%d",sum);//最后输出总数
}
转载请注明出处,有疑问欢迎探讨
博主邮箱 2775182058@qq.com