【DFS练习】素数环

简介: 【DFS练习】素数环

题目描述:

素数环:从1到n这n个数摆成一个环,要求相邻的两个数的和是一个素数。如,n=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

其总数为4

输入:

n的值(n不大于15)

输出:

打印素数环并输出数量,如果不存在素数环则输出 “no solution!”(不输出双引号)。

其实我一开始是用C++写的,但是如果测试集的量级大了之后,iostream用的流要用的时间开销大,所以换成了C语言。


思路:


对于1到n这些数,素数环相当于全排列的子集。

可以试探性的先选一个数,如果下面不符合条件,退回来重新选择。也就是深搜思想。

对于是否是素数,还有这个数是否存在的检查,可以在填方前遍历检查,也可以用空间换时间,建立一个素数数组和是否检查过的数组,降低时间复杂度。


深搜+回溯+剪枝:

#include<stdio.h>
int n, sum = 0;
void printR(int* r){
  for(int i = 0; i < n; i++){
    printf("%d ", r[i]);
  }
  printf("\n");
}
bool isP(int k){
  for(int i = 2; i*i <= k; i++){
    if(k%i == 0) return false;
  }
  return true;
}
bool check(int* r, int i, int cur){
  for(int j = 0; j < cur; j++){
    if(r[j] == i || !isP(i+r[cur-1]))
      return false;
  }
  return true;
}
void dfs(int* r, int cur){
  if(cur == n && isP(r[n-1]+r[0])){
    printR(r);
    sum++;
    return;
  }
  for(int i = 2; i <= n; i++){
    if(check(r, i, cur)){//剪枝
      r[cur] = i;
      dfs(r,cur+1); //向下深搜
      r[cur] = 0;   //回溯
    }
  }
}
int main(){
  scanf("%d",&n);
  int r[n]={0};
  r[0] = 1;
  dfs(r, 1);
  if(sum == 0) printf("no solution!\n");
  return 0;
}

空间换时间:

#include<stdio.h>
// 改进(空间换时间) 
const int maxn = 16;
int isp[2*maxn+1] = {1};
int vis[maxn+1] = {0};
int r[maxn] = {0};
int n, sum = 0;
void printR(){
  for(int i = 0; i < n; i++){
    printf("%d ", r[i]);
  }
  printf("\n");
}
void is_prime(int n){
  isp[1] = isp[2] = isp[3] = 1;
  for(int i = 4; i <= n; i++){
    for(int j = 2; j*j <= i; j++){
      if(i%j == 0){
        isp[i] = 0;
        break;
      }else isp[i] = 1;
    }
  }
}
void dfs(int cur){
  if(cur == n && isp[r[n-1]+r[0]]){
    printR();
    sum++;
    return;
  }
  for(int i = 2; i <= n; i++){
    if(!vis[i] && isp[i+r[cur-1]]){
      r[cur] = i;
      vis[i] = 1;//做标记 
//      printR();
      dfs(cur+1);
      vis[i] = 0;//取消标记 
    }
  }
}
int main(){
  scanf("%d",&n);
//  n = 16;
  is_prime(2*maxn);//生成素数表  
  r[0] = vis[1] = 1;
//  printR();
  dfs(1);
//  printf("%d\n",sum);
  if(sum == 0) printf("no solution!\n");
  return 0;
}
相关文章
|
4月前
|
算法
DFS算法的实现
DFS算法的实现
69 3
|
6月前
|
C++
|
6月前
|
算法 索引
DFS算法及应用(二)
回溯:回溯就是DFS的一种,在搜索探索过程中寻找问题的解,当发现不满足求解条件时,就回溯返回,尝试其他路径。
|
6月前
|
算法
DFS算法及应用(一)
DFS(深度优先搜索)是一种图遍历算法,常用于解决穷举问题,如全排列、迷宫问题、图的连通性等。它沿着树的深度分支进行探索,直至达到叶子节点,若无法继续则回溯。例如,将数字6拆分为3个正整数的递增序列问题可以通过DFS实现,类似地,分糖果问题和买瓜问题同样可以用DFS求解。DFS通常涉及递归或栈结构,通过标记已访问节点避免重复。在编程中,会定义递归函数,设定结束条件,然后枚举可能的情况,并处理下一层节点。
|
机器学习/深度学习 人工智能 定位技术
|
算法
DFS and BFS
DFS and BFS
53 0
|
定位技术
DFS:踏青
DFS:踏青
|
存储 算法 PHP
深度优先搜索(DFS)
深度优先搜索(DFS)
253 0
深度优先搜索(DFS)