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
Sample Output
Note: the number of first circle should always be 1. 翻译: 环是由n个圆圈组成的,如图所示。将自然数1、2、n、n分别放入每个圆中,两个相邻圆的个数之和应为素数。 注:第一圈的数目应始终为1。
Input
You are to write a program that completes above process.
Print a blank line after each case. 翻译:输出格式显示为下面的示例。每一行代表在环圈数从1开始顺时针和anticlockwisely系列。数字的顺序必须满足上述要求。在字典顺序打印解决方案。 您要编写一个程序,完成上述过程。 在每一种情况下打印一条空白线。
6 8
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; }