人生第一个深入理解的DFS题 HDU 1016

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. 翻译:  环是由n个圆圈组成的,如图所示。将自然数1、2、n、n分别放入每个圆中,两个相邻圆的个数之和应为素数。             注:第一圈的数目应始终为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. 翻译:输出格式显示为下面的示例。每一行代表在环圈数从1开始顺时针和anticlockwisely系列。数字的顺序必须满足上述要求。在字典顺序打印解决方案。             您要编写一个程序,完成上述过程。             在每一种情况下打印一条空白线。
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
代码如下
  
  
#include <stdio.h> #include <string.h> int n,prime[50],a[50],vis[50];//a[]数组用来存储每一次适合题意的一组数据 vis[]在dfs中用来判断数字是否在之前的dfs中使用过了
  
  
void isprime() {     int i,j;     for(i = 2;i<50;i++)     prime[i] = 1;     prime[0] = prime[1] = 0;     for(i = 2;i<50;i++)     {         if(prime[i])         for(j = i+i;j<50;j+=i)         prime[j] = 0;//prime[x]数组中x为质数时为1,否则为0.     } }
void dfs(int step)//step代表第几个环 {     int i,j;     if(step == n+1 && prime[a[n]+a[1]])//结束条件     {         for(i = 1;i<n;i++)         printf("%d ",a[i]);         printf("%d\n",a[n]);         return 0;     }     for(i = 2;i<=n;i++)//每一步dfs搜索都需要把这个节点可能的情况搜索一遍         if(!vis[i] && prime[i+a[step-1]])//此数未用并且与上一个放到环中的数相加是素数         {             a[step] = i;             vis[i] = 1;             dfs(step+1);             vis[i] = 0;//将vis[i]清零预备下一次搜索时判断i有没有被使用过         }
}
int main() {
    int cas = 1;     a[1] = 1;     isprime();     while(scanf("%d",&n))     {         printf("Case %d:\n",cas++);         dfs(2);         printf("\n");     }
    return 0; }
  
  
下面是个运行时间更短的方法 很不错的程序
  
  
#include <stdio.h> int num[21],mark[21],n; int prime_num[12] = {2,3,5,7,11,13,17,19,23,29,31,37}; //判断是否是质数,是返回1,不是返回0 int is_prime(int a) {     int i;     for( i = 0; i < 12;i++)     if(a==prime_num[i])return 1;     return 0; } void print_num() {int i;     for( i = 1; i < n;i++)     printf("%d ",num[i]);     printf("%d",num[n]); } int dfs(int post,int pre,int flag) {     int i;     //如果不符合,直接返回     if(!is_prime(pre+post))     return ;     num[flag] = pre;     if(flag==n&&is_prime(pre+1))     {         print_num();         printf("\n");     }     //使用过了这个数字就标记为0     mark[pre] = 0;     for( i = 2;i<=n;i++)     if(mark[i]!=0)dfs(pre,i,flag+1);     //标记位恢复原状     mark[pre] = 1; } int main() {     int count,i;     count = 1;     while(scanf("%d",&n)!=EOF)     {         for( i = 1; i <= n; i++)         mark[i] = 1;         num[1] = 1;         printf("Case %d:\n",count++);         if(n==1)printf("1\n");         for(i = 2;i<=n;i++)         dfs(1,i,2);         printf("\n");     }     return 0; }
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值