【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;
}
相关文章
|
11月前
|
算法
DFS and BFS
DFS and BFS
39 0
八皇后(dfs全排列)
八皇后(dfs全排列)
62 0
|
算法
【和zqy学算法】Day1:DFS与BFS
【和zqy学算法】Day1:DFS与BFS
128 0
|
测试技术
输出全排列 (20 分)(dfs模板题)
输出全排列 (20 分)(dfs模板题)
94 0
|
定位技术 ice
POJ-3009,Curling 2.0(DFS)
POJ-3009,Curling 2.0(DFS)
7-121 深入虎穴 (25 分)(dfs,bfs)
7-121 深入虎穴 (25 分)(dfs,bfs)
135 0
|
数据采集 算法 容器
一文带你了解dfs和bfs算法
dfs算法又称深度优先搜索,是计算机术语。 1、dfs是一种在开发爬虫早期使用较多的方法,是搜索算法的一种。 2、dfs的目的是要达到被搜索结构的叶结点,即那些不包含任何超链的HTML文件。 3、dfs根据已有的邻接矩阵或邻接表用递归方法编写深度优先搜索遍历算法,并输出遍历结果 作为搜索算法的一种,DFS对于寻找一个解的NP(包括NPC)问题作用很大。但是,搜索算法毕竟是时间复杂度是O(n!)的阶乘级算法,它的效率非常低,在数据规模变大时,这种算法就显得力不从心了。当节点v的所有边都己被探寻过,搜索将回溯到发现节点v的那条边的起始节点。这一过程一直进行到已发现从源节点可达的所有节点为止
360 0
一文带你了解dfs和bfs算法
黑白棋_lduoj_dfs深搜
Description Lagno是一种二人智力游戏。游戏设有一个黑方和一个白方。游戏桌面是正方形的,包含8行8列。 如果黑方玩家走出这样一步棋:将一枚黑子放在任一空格上,而在这个空格的八个方向(上、下、左、右和4个对角线方向)的至少一个方向上有一排白子被夹在这枚新下的黑子和其他黑子之间,任何方向,在新黑子和原来黑子之间的所有白子都要变成黑子。为这个游戏设计一个程序,计算一步棋中黑方能转变的白子数量的最大值。 Input 输入文件lango.in共8行,每行8个字符;“.”代表一个空格;“B”代表黑子,“W”代表白子
87 0
LeetCode——全排列(DFS)
LeetCode——全排列(DFS)
129 0
LeetCode——全排列(DFS)