HDU 1016 Prime Ring Problem(素数环)(DFS入门水题)

让我们先看一下HDU1016的问题描述:

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

Prime Ring Problem
Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 54084    Accepted Submission(s): 23945
Problem Description
A ring is compose of n circles as shown in diagram. Put natural number 1, 2, ..., n into each circle separately, and the sum of numbers in two adjacent circles should be a prime.


Note: the number of first circle should always be 1.
Input
n (0 < n < 20).
Output
The output format is shown as sample below. Each row represents a series of circle numbers in the ring beginning from 1 clockwisely and anticlockwisely. The order of numbers must satisfy the above requirements. Print solutions in lexicographical order.
You are to write a program that completes above process.
Print a blank line after each case.
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
 
Source
Asia 1996, Shanghai (Mainland China)


题目意思相信大家都明白了,意思就是组成一个素数环,环内相邻的2个数之和为素数,且开头为1,比如输出的第一组实例:1 4 3 2 5 6,1和4相加为素数,1和3不是相邻(看图就知道了),这个题目就用到了DFS深度优先搜索,关于深度优先搜索,这里可以提供一个入门的可以理解一下的链接:http://blog.csdn.net/u011437229/article/details/53188837
在这里,DFS的结束条件是所有数枚举完毕而且相邻两个数之和为素数时结束搜索,输出样例,这里还要注意就是有关输入方面的问题,下面贴出代码:
#include <bits/stdc++.h>
using namespace std;
    int vis[50],a[50],prime[50],n;//遍历数组,结果保存数组,是否为素数的判断数组,输入的数
        void isprime()//判断是否为素数
        {
        int i,j;
        for(i=0;i<50;i++)
        prime[i]=1;//初始值为1(表示假设全部是素数)
        prime[0]=0;
        prime[1]=0;//0不是素数也不是合数,1与0相同性质,但是题目要求初始输出环开头为1
        for(i=2;i<50;i++)//从2到50遍历所有有关倍数
            {
            if(prime[i])//如果是素数,那素数的倍数不是素数
                {
                for(j=i+i;j<50;j+=i)
                prime[j]=0;//素数的倍数全部不是素数,变成0
                }
            }
        }
        void dfs(int step)//DFS核心代码,step表示步数
            {
            int i,j;
            if(step == n+1 && prime[a[n]+a[1]])//判断条件,即步数到N且头尾两数之和为素数
            {
                for(i=1;i<n;i++)//输出段
                printf("%d ",a[i]);
                printf("%d\n",a[n]);
                return ;
            }
            for(i=2;i<=n;i++)//如果上面条件不满足,执行搜索段
                {
                if(!vis[i]&&prime[i+a[step-1]])//如果未被访问到且前一个数和该数之和为素数
                {
                    a[step]=i;//该步数下的数为i
                    vis[i]=1;//访问数组标记
                    dfs(step+1);//关键,深搜的主要思想是递归回溯,利用本身进行第二次搜索
                    vis[i]=0;//如果搜索失败,访问标记清空
                }
                }
            }
        int main()
        {
            int cnt=1;//记录实例数
            a[1]=1;//第一个输出永远是1
            isprime();//素数数组预处理(OJ的特点,在读入数据之前的时间不算在运行时间内)
            while(~scanf("%d",&n))//OJ的特点2,循环输入
            {
                memset(vis,0,sizeof(vis));//清空遍历数组
                printf("Case %d:\n",cnt++);
                dfs(2);//开始深搜
                printf("\n");
            }
            return 0;
    }
这道题的关键还是掌握有关DFS的知识,这道题在DFS的题目里面算入门级别,只要能找到判断条件就可以直接写出

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值