Prime Ring Problem(素数环)递归回溯问题

Prime Ring Problem(素数环)

题目描述:
余队长某天ak太多了心烦,想带领他的队员做游戏 。

游戏内容如下:

当余队长喊出一个数字n时,便有n个队员,身上带着1到n的数字,手牵手拉成一个环。当环里的每个人相邻两人身上数字之和都为素数时,便找到了一个环。当找出所有的环时,游戏便结束。

Note: 每个环的第一个数字必须是1 在这里插入图片描述
Input

n (0 < n < 20).

Output
输出格式如下方输出样例所示。

每行一串数字表示一种环中数字的排列顺序。数字的顺序必须满足:从1开始,顺时针或逆时针。按字典序输出所有解决方案。您将编写一个完成上述过程,帮助大家顺利完成游戏的程序。

别忘了在每组方案后面输出一个空行。

Sample Input

6 
8

Sample Output

Case 1:
1 4 3 2 5 6
1 6 5 2 3 4

Case 2:
1 2 3 8 5 6 7 4
1 2 5 8 3 4 7 6
1 4 7 6 5 8 3 2
1 6 7 4 3 8 5 2

思路
运用回溯和递归的思想

AC代码:
方法一:

#include<stdio.h>
#include<math.h>
bool b[1010];    //定义一个数组用来存是否为素数,1为素数,0为合数(不是素数),因为bool只有0和1所以定义bool,当然int型也可以,记得数组开大点,要不然会超限
int ii;
int total;
int a[101];
//定义判断函数
//pd就是判断的意思,定位bool型和数组b的原因一样
bool pd(int x,int y)    //判断是否为素数
{
    int k,e;
    e=x+y;  //用e表示两个数相加,因为是两个数相加判断是否为素数
    for(k=2;k<=sqrt(e);k++) 
    {
        if(e%k==0)
        {
            return 0;   //表示不是素数
        }
    }
    return 1;       //没有一个数可以整除,表示为素数,返回1
}
//定义打印函数
int print()
{
    total++;
    for(int j=1;j<=ii;j++)
    {
        if(a[1]==1&&j!=ii)
        {
             printf("%d ",a[j]);    //每个数要用空格隔开,但最后一个数直接换行,用一个if判断就行了。
        }                           //如果不这样会格式错误
       else if(a[1]==1&&j==ii)
       {
           printf("%d",a[j]);
       }
       else return 0;               //不retur会打印空行
    }
    printf("\n");
    //return 0;
    //因为定义的是int,所以要有返回值,但是对答案不影响,不打retur 0,答案不会错所以我注释掉了。
}
//递归
int search(int t)
{
    for(int i=1;i<=ii;i++)
    {
        if(pd(a[t-1],i)&&(!b[i]))
        {
            a[t]=i;
            b[i]=1;
            if(t==ii)
            {
                if(pd(a[ii],a[1]))print();  //判断+打印
            }
            else search(t+1);               //递归
            b[i]=0;     //把bool b从新赋值为0,这里是回溯的思想
        }
    }
   // return 0;    
   //和上面的print函数的 retur 0原因一样。   
}
int main()
{
    int c=1;        //定义一个计数器,输出的时候让输出Case n:。
    while(~scanf("%d",&ii))     //多组输入
    {
        printf("Case %d:\n",c);
        search(1);			//调用search函数
        printf("\n");       //题目要求每组后面多一个换行
        c++;        //每次输入完后计数器加一
    }
    return 0;
}

注:用C语言中没有bool类型。

方法二:

#include<cstdio>
#include<stack>
#include<cstring>
#include<iostream>
#include<cmath>
#include<algorithm>
#include<vector>
#include<queue>
using namespace std;
const int N = 25;
int a[N],b[N];
int n;
bool prime(int x)
{
    if(x<=1) return false;
    for(int i=2;i<=sqrt(x);i++)
    {
        if(x%i==0) return false;
    }
    return true;
}
void dfs(int x)
{
    if(x==n&&prime(a[1]+a[n]))  // 特判首尾
    {
        for(int i=1;i<n;i++) cout<<a[i]<<' ';
        cout<<a[n]<<endl;
    }
    else
    {
        for(int i=2;i<=n;i++)   // 记录整个循环过程中符合的数列,生成满足数列得下一位
        {
            if(!b[i]&&prime(a[x]+i))
            {
                a[x+1]=i;   // 验证下一个数符合不符合;
                b[i]=1;     // 用完进行标记
                dfs(x+1);   // 寻找下一个
                b[i]=0;     // 还原
            }
        }
    }
}

int main()
{
    int ans=1;
    while(cin>>n)
    {
        memset(a,0,sizeof(a));
        memset(b,0,sizeof(b));
        a[1]=1;
        printf("Case %d:\n",ans++);
        dfs(1);
        cout<<endl;
    }
    return 0;
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值