把博客园图标替换成自己的图标
把博客园图标替换成自己的图标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 @   Starlight_Glimmer  阅读(153)  评论(0编辑  收藏  举报  
编辑推荐:
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
浏览器标题切换
浏览器标题切换end
点击右上角即可分享
微信分享提示