zoukankan      html  css  js  c++  java
  • goj 素数环(dfs)

    Problem Description:

    如图所示,环由n个圆组成。 将自然数1,2,...,n分别放入每个圆中,并且两个相邻圆中的数字总和应为素数。

    注意:第一个圆圈的数量应该始终为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
    解题思路:dfs。先打表记录40以内是素数的数组isp,因为相邻数之和有可能最大为39,所以只需枚举到39。关于字典序输出,这里每枚举到当前这个数,从2开始到n枚举哪些数是满足条件,有的话就将当前这个数记录在path数组中,并且标记这个数已经被访问,再递归下去寻找下一个数,如果递归不满足条件的话,将当前这个数置为0。每当cur==n时就输出当前素数环。其中有一个剪枝的操作,如果给定的整数n为奇数,那么肯定不存在素数环,(因为肯定存在两个奇数相邻,而奇数与奇数的和为偶数,所以一定不是素数环)这个节省了不少递归时间,不然老是TLE-_-||。
    AC代码:
     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 int n,isp[40]={0},vis[20],path[20];//vis数组是保存标记,path是记录
     4 int is_prime(int t)//判断素数
     5 {
     6     for(int i=2;i*i<=t;++i)
     7         if(t%i==0)return 0;
     8     return 1;
     9 }
    10 void dfs(int cur)
    11 {
    12     if((cur==n) && isp[path[1]+path[n]]){//递归边界 如果cur==n && isp(1+path[n])是素数,则终止条件
    13         for(int i=1;i<n;i++)
    14             cout<<path[i]<<' ';
    15         cout<<path[n]<<endl;
    16         return ;
    17     }
    18     else{
    19         for(int i=2;i<=n;++i){//尝试放置每个数i
    20             if(!vis[i] && isp[i+path[cur]]){  //如果i没用过
    21                 path[cur+1]=i;//且i加上与之相邻的上一个数之和是素数,则把它赋给path[cur+1];
    22                 vis[i]=1; //设置使用标志
    23                 dfs(cur+1); //深搜
    24                 vis[i]=0; //清除标志
    25             }
    26         }
    27     }
    28 }
    29 int main()
    30 {
    31     for(int i=2;i<40;++i)  //生成素数表,枚举到最大的2倍即可
    32         isp[i]=is_prime(i);
    33     int k=1;     //Case情况数
    34     while(cin>>n){
    35         cout<<"Case "<<k++<<':'<<endl;
    36         memset(vis,0,sizeof(vis));
    37         vis[1]=1,path[1]=1;//将1作为path开头,且标记已访问
    38         if(n>0 && (n%2==0))dfs(1);//剪枝,如果是偶数的话,必有素数环,从1开始深搜
    39         cout<<endl;
    40     }
    41     return 0;
    42 }
     
  • 相关阅读:
    poj 1698 二分图多重匹配
    poj 3207 2-sat
    hdu4932 Miaomiao's Geometry
    hdu4924 Football Manager
    hdu4914 Linear recursive sequence
    hdoj4906 Our happy ending(2014 Multi-University Training Contest 4)
    poj1987 Distance Statistics
    poj3342 Party at Hali-Bula
    C/C++ 调用qsort/sort 对字符数组排序的cmp函数写法
    poj1947 Rebuilding Roads
  • 原文地址:https://www.cnblogs.com/acgoto/p/8810982.html
Copyright © 2011-2022 走看看