zoukankan      html  css  js  c++  java
  • hdu 1016 Prime Ring Problem 解题报告

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1016

         题意很简单,就是输入一个n,把1~n的数填入n个圆圈里,但是要满足相邻两个数的和是素数,输出的时候要按符合条件的序号按递增的形式输出,每个实例之间要有空行。

         这是一道dfs的经典题目,其中还要结合素数的打表思想。一开始觉得给出的n<20,那么相邻两数之和最大也就37(18+19),40以内的素数可以很简单地存入prime数组中:2、3、5、7、11、13、17、19、23、29、31、37(对应的数组下标是0~11)。然后在dfs中,判断相邻两数之和是否是素数,直接从prime数组里查找即可。但是发现这样查找非常繁琐,最坏的情况(虽然这是不可能的)每个和都要查找11次。如果是19个数(n最大为19),就要查19×11次了。看了别人打表的思想后,才发现,这样可以节省很多时间。注意,prime的数组下标代表1~n的数,存储的数指示了该数是否是素数(0:不是素数 1:是素数)

         至于dfs里面,有一个要注意的地方是,素数环里首尾元素之和的判断很容易忘记,而这个判断好之后,也就代表整个序列是符合条件的,可以输出。具体代码如下:

     1 #include <iostream>
     2 using namespace std;
     3 
     4 int visit[40], prime[40], cur[40];
     5 int n;
     6 
     7 int is_prime(int x)
     8 {
     9     int i;
    10     if (x == 2)
    11         return 1;
    12     else if (x % 2 == 0 || x == 1)
    13         return 0;
    14     for (i = 3; i * i <= x; i += 2)
    15     {
    16         if (x % i == 0)
    17             return 0;
    18     }
    19     return 1;
    20 }
    21 
    22 void dfs(int p)
    23 {
    24     int i;
    25     if (p == n && prime[cur[n] + 1])  //素数环里首尾元素之和的判断
    26     {
    27         printf("1");
    28         for (i = 2; i <= n; i++)
    29         {
    30             printf(" %d", cur[i]);
    31         }
    32         printf("\n");
    33     }
    34     for (i = 2; i <= n; i++)
    35     {
    36         if (prime[cur[p]+i] && !visit[i]) //未访问过的数i与它的前一个数(cur[p])之和是素数
    37 { 38 cur[p+1] = i; //cur指示下一个位置p+1,新的cur作为下一个未访问过的数的前一个数 39 visit[i] = 1; //该数已被访问 40 dfs(p+1); //搜索下一个未访问过的数 41 visit[i] = 0; //恢复递归前的未访问状态 42 } 43 } 44 } 45 46 int main() 47 { 48 int i, cas = 0; 49 for (i = 1; i <= 40; i++) 50 prime[i] = is_prime(i); //打表,0代表不是素数,1代表是素数,为dfs的查表作预处理 51 while (cin >> n) 52 { 53 memset(visit, 0, sizeof(visit)); 54 memset(cur, 0, sizeof(cur)); 55 printf("Case %d:\n", ++cas); 56 cur[1] = 1; //从1开始,代表位置1 57 visit[1] = 1; //由于要从1开始打印,可以转换为visit[1]已经被访问 58 dfs(1); //从1开始搜索 59 printf("\n"); 60 } 61 return 0; 62 }

    2014.7.23

     1 #include <iostream>
     2 #include <cstdio>
     3 #include <cstdlib>
     4 #include <cstring>
     5 using namespace std;
     6 
     7 const int maxn = 40;
     8 int prime[maxn], vis[maxn], s[maxn], n;
     9 
    10 bool is_prime(int n)
    11 {
    12     if (n == 2)
    13         return true;
    14     for (int i = 2; i*i <= n; i++)
    15     {
    16         if (n % i == 0)
    17             return false;
    18     }
    19     return true;
    20 }
    21 
    22 void dfs(int p)
    23 {
    24     if (p-1 == n)   // 开始写成p == n,找了差不多两日, = =
    25     {
    26         if (prime[s[p-1]+1]) 
    27         {
    28             for (int i = 1; i <= n-1; i++)
    29                 printf("%d ", s[i]);
    30             printf("%d\n", s[n]);
    31             return;
    32         }
    33     }
    34     for (int i = 2; i <= n; i++)
    35     {
    36         if (prime[s[p-1]+i] && !vis[i])
    37         {
    38             vis[i] = 1;
    39             s[p] = i;
    40             dfs(p+1); 
    41             vis[i] = 0;
    42         }
    43     }
    44 }
    45 
    46 int main()
    47 {
    48     int cas = 0;
    49     memset(prime, 0, sizeof(prime));
    50     for (int i = 2; i <= maxn-3; i++)
    51     {
    52         if (is_prime(i))
    53             prime[i] = 1;
    54     }
    55     while (scanf("%d", &n) != EOF)
    56     {
    57         printf("Case %d:\n", ++cas);
    58         vis[1] = 1;
    59         s[1] = 1;
    60         dfs(2);
    61         printf("\n");
    62     }
    63     return 0;
    64 }
    65  
  • 相关阅读:
    后端结对编程报告(2018.6.6)
    Burn Down Chart(2018.6.4~2018.6.10)
    C#多线程List的非线程安全性
    C#泛型参数多线程与复杂参数多线程
    Java学习之App开发公司手机端设想
    Java学习之SpringBoot整合SSM Demo
    Java学习之Mysql结构优化
    Java学习之Dubbo+ZooKeeper分布式服务Demo
    C# 面向切面编程--监控日志记录方案
    C# 通用类型转换方法
  • 原文地址:https://www.cnblogs.com/windysai/p/3057350.html
Copyright © 2011-2022 走看看