zoukankan      html  css  js  c++  java
  • 素数环问题(递归回溯)

    【原创】

    有这样一个有趣的问题,输入n,然后取1<x<n中的数,围成一个环,使得相邻的两个数和为素数,并且第一个数一定是1,输出所有的可能序列,比如说输入n=6,那么得到的序列是1 4 3 2 5 6、1 6 5 2 3 4这样两个序列,不难验证,这个环就满足条件,那么利用我们的代码来实现

    利用递归回溯的方法,即试探性的往下走,若走到一个地方发现不满足条件,则返回上一个状态从新选择,结合这一主要思想,有如下代码,其中仍然接受多组输入数据,即可以多次输入n,

    代码:

     1 #include <stdio.h>
     2 #include <stdlib.h>
     3 #include <string.h>
     4 //递归回溯法
     5 int ans[22];// 保存环中每一个被放入的数
     6 bool hash[22];//标记之前已经被放入的数
     7 int n;//全局的n,表示输入的数字,题目要求1<n<17,即最大为16
     8 int prime[]={2,3,5,7,11,13,17,19,23,29,31,37,41};//由于n最大为16,因而其最大和素数在这里面
     9 bool judge(int x){
    10     //判断x是否为素数
    11     for (int i = 0; i<13; i++) {
    12         if (prime[i]==x) {
    13             return true;//
    14         }
    15     }
    16     return false;//不是
    17 }
    18 //检查解
    19 void check(){
    20     if(judge(ans[n]+ans[1])==false)return;//这里只用检查最后一个数字和第一个数字和是否为素数了
    21     for(int i = 1;i<=n;i++){
    22         if (i!=1) {
    23             printf(" ");//最后一个无空格
    24         }
    25         printf("%d",ans[i]);
    26     }
    27     printf("
    ");
    28 }
    29 //递归枚举
    30 void DFS(int num){//num为当前已经放入环中的数字量
    31     if(num>1)
    32         if (judge(ans[num]+ans[num-1])==false) return;//表示相邻的这两个数和不为素数
    33     if(num==n){//当放入个数已经达到n,检查了,这就是为什么check函数中只用判断最后一次放入是否有效,其实,这里完全不用check,直接在这里判断judge(ans[n]+ans[1])==true?.然后输出,但是为了方便分离,所以单独写了一个函数
    34         check();
    35         return;
    36     }
    37     for(int i = 2;i<=n;i++){//放入一个数,这就是递归的魅力,要脑袋里结合一组数据来查看这里的执行
    38         if(hash[i]==false){//i是待放入环中的数字,
    39             hash[i]=true;
    40             ans[num+1] = i;//一定是num+1哦,
    41             DFS(num+1);
    42             hash[i] = false;//当在上一层中return回来之后,这里一定要将hash[i]重新设置为false哦;方便后继的使用,
    43         }
    44          
    45     }
    46 }
    47 int main() {
    48 int Case = 0;
    49     while (scanf("%d",&n)!=EOF) {
    50         Case++;
    51         for (int i = 0; i<22; i++) {
    52             hash[i] = false;
    53         }
    54         ans[1] = 1;//第一个横为1,上面已经做了标记处理,所以这里不再需要考虑ans数组中残留的上一组数据
    55         printf("Case %d:
    ",Case);
    56         hash[1] = true;
    57         DFS(1);//一开始都是从放入环1开始
    58       printf("
    ");
    59     }
    60     return 0;
    61 }
    62  
    63 /**************************************************************
    64     Problem: 1459
    65     User: Numen_fan
    66     Language: C++
    67     Result: Accepted
    68     Time:600 ms
    69     Memory:1020 kb
    70 ****************************************************************/

    注:这份代码注释蛮详细的,建议结合一组输入,跟随着代码进行简单的调试,在草稿纸上进行手工理解,才能彻底理解;

  • 相关阅读:
    20159302 《网络攻击与防范》第三周学习总结
    Json序列化空时间字段出异常
    IIS 原理
    谴责盛大Bambook 的ADB.EXE流氓进程
    Fix: ADB server didn’t ACK
    在线UI设计
    解决装Windows蓝屏问题。
    如何成为一个C++高级程序员
    Python编程规范及性能优化
    iDempiere 使用指南 插件安装过程
  • 原文地址:https://www.cnblogs.com/numen-fan/p/6511006.html
Copyright © 2011-2022 走看看