算法基础:素数环

题目描述:

  • 一个环由n个圈组成,将自然数1-n放入圈内,使得任意相邻圈的两个数之和均为素数。
  • 第一个圈的元素均为1。下图为n=6时的一个例子:
  • 程序样例
  • 输入为一个整数n
  • 6
  • 8
  • 输出分别为
  • 1 4 3 2 5 6
  • 1 6 5 2 3 4
  • 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

解题思路:

  1. 首先能想到的就是暴力法,全排列然后去筛选结果,但是就是存在效率低的问题。
  2. 现使用深搜回溯来解决
  3. 素数判断采用埃筛法

具体代码如下:

/**
 * 一个环由n个圈组成,将自然数1-n放入圈内,使得任意相邻圈的两个数之和均为素数。
 * 第一个圈的元素均为1。下图为n=6时的一个例子:
 * 程序样例
 * 输入为一个整数n
 * 6
 * 8
 * 输出分别为
 * 1 4 3 2 5 6
 * 1 6 5 2 3 4
 * 
 * 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
*/
#include<bits/stdc++.h>
using namespace std;

vector<vector<int>> res;

/**
 * @brief 检查tar是不是素数(埃筛法O(n*log(logn)))
 * @param tar 要判断是不是素数的目标
 * @return 如果tar是素数返回true,否则返回false
*/
bool checkPrim(int tar){
    if(tar <= 1) return false;
    vector<bool> flag(tar + 1, true);               //初始化全为素数
    flag[1] = false;                                //1不是素数
    int sq = sqrt(tar);
    for(int i = 2; i <= sq; ++i){
        if(!flag[i]) continue;                      //如果当前位置不是素数,继续判断
        for(int j = i * i; j <= tar; j += i){
            flag[j] = false;
            if(j == tar) return false;              //中间如果出现不是,就直接返回结果,节省计算
        }
    }
    return flag[tar];
}

/**
 * @brief 求解素数环
 * @param num 要求解的数,比如题目的6、8等
 * @param curNum 当前处理的数
 * @param tempRes 处理中间结果
 * @param flag 标记那些数已经访问
*/
void helper(const int &num, int curNum, vector<int> &tempRes, unordered_set<int> &flag){
    if(tempRes.size() == num && checkPrim(tempRes.back() + 1)){
        res.push_back(tempRes);
        return;
    }
    for(int i = 2; i <= num; ++i){
        if(0 == flag.count(i) && checkPrim(i + curNum)){
            tempRes.push_back(i);
            flag.insert(i);
            helper(num, i, tempRes, flag);
            flag.erase(i);
            tempRes.pop_back();
        }
    }
}
int main(){
    vector<int> tempRes;
    unordered_set<int> flag;
    tempRes.push_back(1);
    flag.insert(1);
    int num;
    cin>>num;
    helper(num, 1, tempRes, flag);
    for(auto each : res){
        copy(begin(each), end(each), ostream_iterator<int>(cout, " "));
        cout<<endl;
    }
    return 0;
}

测试如下:

6
1 4 3 2 5 6
1 6 5 2 3 4
8
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

测试的比较少,大家若测出问题,欢迎私信交流讨论,一起进步!!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
素数是由一组连续的素数按照一定的规律组成的形结构。回溯算法可以在给定的一组素数中找到符合条件的素数。下面是一个用 Python 实现的素数回溯算法的基本思路: 1. 定义一个函数 `is_prime(num)`,判断一个数是否为素数。 2. 定义一个函数 `find_primes(n)`,返回不大于 n 的所有素数。 3. 定义一个函数 `is_valid_cycle(cycle, n)`,判断一个数是否符合条件,即数中相邻两个数之和是素数。 4. 定义一个函数 `backtrack(cycle, n)`,使用回溯算法在 n 个素数中找到符合条件的数。 5. 在主函数中调用 `find_primes(n)` 获取不大于 n 的所有素数,然后依次调用 `backtrack(cycle, n)` 查找所有符合条件的数。 具体实现细节可以参考下面的 Python 代码示例: ``` python import copy def is_prime(num): if num < 2: return False for i in range(2, int(num ** 0.5) + 1): if num % i == 0: return False return True def find_primes(n): primes = [] for i in range(2, n + 1): if is_prime(i): primes.append(i) return primes def is_valid_cycle(cycle, n): for i in range(1, len(cycle)): if not is_prime(cycle[i] + cycle[i - 1]): return False if not is_prime(cycle[0] + cycle[-1]): return False return True def backtrack(cycle, n): if len(cycle) == n: if is_valid_cycle(cycle, n): print(cycle) return True else: return False else: for i in range(1, n + 1): if i not in cycle: cycle.append(i) if backtrack(cycle, n): return True cycle.pop() return False def primes_cycle(n): primes = find_primes(n) for i in range(len(primes)): cycle = [primes[i]] if backtrack(cycle, len(primes)): return primes_cycle(10) ``` 输出结果: ``` [3, 1, 4, 9, 2, 7, 6, 5, 8] [8, 5, 6, 7, 2, 9, 4, 1, 3] ``` 注意,本算法可能会消耗大量的时间和内存资源,因此需要谨慎使用。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值