zoukankan      html  css  js  c++  java
  • 素数环 与 算法 全排列

    在说起全排列前,先说一下昨天碰到的一个题目(答案不是我做出来的,但是我感觉有好多个亮点,贴出来方便日后的学习):

    素数环

    时间限制:1000 ms  |  内存限制:65535 KB
    难度:2
     
    描述

    有一个整数n,把从1到n的数字无重复的排列成环,且使每相邻两个数(包括首尾)的和都为素数,称为素数环。

    为了简便起见,我们规定每个素数环都从1开始。例如,下图就是6的一个素数环。

     
    输入
    有多组测试数据,每组输入一个n(0<n<20),n=0表示输入结束。
    输出
    每组第一行输出对应的Case序号,从1开始。
    如果存在满足题意叙述的素数环,从小到大输出。
    否则输出No Answer。
    样例输入
    6
    8
    3
    0
    样例输出
    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
    Case 3:
    No Answer








    这个题的解法我考虑了很久,怎么说呢,感觉上并不是一道难度很大的题,实际操作起来却又无从下手。我说一下我的思考过程
    首先,这牵扯到寻找素数,但是呢,不是简单的找素数,而是两个数的和,在[1,n]之间的两个数m,n的和

            有多组测试数据,每组输入一个n(0<n<20),n=0表示输入结束。

    这句话可以看出输入的n,最大,也就20.那么,即使在跑程序的时候,当真输入为20,最大的的一个和值也就是20+20=40,那么,我完全可以把[1,40]间的素数全部找出来并建立一个数
    组s[40],然后在[1,n]间查看,看哪两个数的和是素数,通过在数组s[40]里查找是否符合,若符合,将符合的值存放在一个数组里,而后输出。
    #include <stdio.h>
    #include<string.h>
    int count,sa[40];    //  coount 用于控制输出流    sa[]是一个用来显示区间[2,42]内每个数是否为素数的数组,若为素数,其对应的sa[j]=1
     
    /*** found 函数的定义,据作者说是由全排列改编过来的 ***/ 
    
    
    
    void found(int n,int cur,int a[],int flag[]){  // 传入的 n 为 in[]数组中的元素,即输入值;  cur 初始值为1  是用于控制a[]的下标  ; a[]是一个a[0]=1的用于存放可满足数的数组; 
                                                  // flag[]是一个初始值全部置0的数组 , 用于储存在判定检查过程中的数是否为要用的值后的布尔值
                                                
        if(cur==n&&sa[a[0]+a[cur-1]])            // 这里用cur 与 输入值 n 进行比较判断  也就是说 a数组里存放的个数最多 n个,最多把[1,n]之间的值全部放进去,或者说数组a里的最大值肯定不能大于n   
    {                                     
        {                                         
            for(int i=0;i<n;i++)            
                printf("%d ",a[i]);                //  那么,当a数组检查n是否可以存放时,这次遍历也就到此结束了,也就是该输出数组a了
            putchar('
    ');                    
            count=0;                            
        }    
    }
    /***** 在cur!=n时,需要进一步的检查时,利用递归,在区间[2,n],以此将满足的数存放在a[]中 *****/
        else                                                                                   //
            for(int i=2;i<=n;i++)                                                              //
            if(!flag[i]&&sa[i+a[cur-1]])                                                       //              
            {                                                                               //
                a[cur]=i;                                                                  //
                flag[i]=1;                                                                //
                found(n,cur+1,a,flag);                                                   //
                flag[i]=0;                                                              //
            }                                                                          //
    }                                                                                 //
    /*********************************************************************************/ 
    int main(void)
    {
        int i=0,a[20],in[100],flag[20];   // in[20] 用于存放输入 
        memset(sa,0,sizeof(sa));            
        memset(flag,0,sizeof(flag));
    /***********************************************************/ 
        for(int ok=1,k=2,j=2;j<40;j++,ok=1)                   //
        {                                                    //
            for(int i=2;i<=j/2;i++)                         //   在区间[2,40]里进行是否为素数的判定   用j控制数组sa的下标,同时,j还是一个数列【2,,40】 
            {                                              //
                if(j%i==0)    ok=0;                       //  若为素数,sa[j]=1,否则不对sa[j]处理,即为0 
            }                                            //
            if(ok) sa[j]=1;                             //
        }                                              //
    /**************************************************/    
        
    /**************************************/
        do                                  //    我很喜欢这段控制输入的代码
        {                                 //     
            scanf("%d",&in[i++]);      //   很简单  但是很巧妙 
        }while(in[i-1]);              //    
    /********************************///        大方  优雅 
        a[0]=1;    
        for(int j=1;j<i;j++)        
        {
            count=1;   
            printf("Case %d:
    ",j);  // j 显示输入的数据的个数  
            if(!(in[j-1]%2)||in[j-1]==1) found(in[j-1],1,a,flag);  // if里判定 in[]数组里的元素是否为奇数 或者是为1   两种情况均调用函数 
            if(count)    printf("No Answer
    ");   
        } 
        return 0;
    }

     先简单简单注释一下,可能在匆忙之中有一些错误,哪位有发现,多谢指出

  • 相关阅读:
    从SAPI 5.1中提取中文发音引擎
    多图:你没见过的古董级PC(zz)
    难搞的证书
    原来VS.Net 2005正式版真的发布了
    Google要改进OpenOffice 并公布其搜索计算数据中心细节(zz)
    AMD CPU市占率突破20%!(zz)
    重定向页面会Alert()不了?
    忍无可忍,希望大家不要来苏州园区工作
    MSN登陆不了怎么办
    网易126免费域名去广告
  • 原文地址:https://www.cnblogs.com/zhangzimu/p/6187187.html
Copyright © 2011-2022 走看看