把博客园图标替换成自己的图标
把博客园图标替换成自己的图标end

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);//最后输出总数 
}


posted @ 2017-06-02 14:45  Starlight_Glimmer  阅读(130)  评论(0编辑  收藏  举报  来源
浏览器标题切换
浏览器标题切换end