素数环dfs回溯算法的一点优化

描述

 有一个整数n,把从1到n的数字无重复的排列成环,且使每相邻的两个数(包括首和尾)的和都为素数,称为素数环。为了简便起见,我们规定每个素数环都从1开始。例如,6的一个素数环:
 1 4 3 2 5 6
 请编写一个程序,给定一个输入n(0<n<20),如果存在满足要求的素数环,从小到大输出。否则,输出No Answer。

  这道题我采用的是dfs加上回溯法来做的,回溯过程也很简单,其他博客里面肯定也会讲到,只是在dfs过程中有一个trick我觉得很不错,分享于此:
  首先全局定义一个数组

int Next_prime[1001];//Next_prime[i]表示大于i的最小的质数

  然后main函数中对其初始化

    {
        int j = 1;
        int pri = prime[j];// prime[i]代表第i个质数
        for(int i = 1; i < 501; i++)
        {
            if(i >= pri)
            {
                j ++;
                pri = prime[j];
            }
            Next_prime[i] = pri;
        }
    }

  然后在dfs中不是在最后位置的时候

    {
        int prenum = round[po - 1];/*round[i]代表环上第i个数是多少,po为dfs中当前环上第po个位置,prenum代表前环上前一个数字*/
        int ne = Next_prime[prenum];
        int d = ne - prenum;/*尝环将环后一个数字更改为d,ne一定是个质数*/
        while(d <= n )//n是环的长度
        {
            if(d > 0 && !is_used[d])
            {
                round[po] = d;
                is_used[d] = 1;
                dfs(po + 1);//尝试下一个位置的值
                is_used[d] = 0;//回溯
            }
            ne = Next_prime[ne];
            d = ne - prenum;/*下一次尝试时只需要ne = Next_prime[ne],保证ne仍是质数而且d增大了 */
        }
    }

  这样的好处,就是减少了判断是否是质数的次数,当然,这个trick也无法改变素数环本身数据指数增长的事实,只能稍稍简化运算。
  另外,当n为奇数时,一定不存在素数环,这是由于抽屉原理,一定有两个非一的奇数相邻,其和便为偶数了,如果不考虑这个的话,可能ac不了。

附:素数环个数 Gx
G(2)=1,G(4)=2,G(6)=2,G(8)=4,G(10)=96,G(12)=1024,G(14)=2880,
G(16)=81024,G(18)=770144,G(20)=6309300,G(22)=213812336
可以看出来随着个数的增长,这个trick并没有太大用处…

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值