HD_1016Prime Ring Problem(dfs)

来源:互联网 发布:淘宝改评价步骤 编辑:程序博客网 时间:2024/05/22 17:18

Prime Ring Problem

Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 36882    Accepted Submission(s): 16249


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
68
 

Sample Output
Case 1:1 4 3 2 5 61 6 5 2 3 4Case 2:1 2 3 8 5 6 7 41 2 5 8 3 4 7 61 4 7 6 5 8 3 21 6 7 4 3 8 5 2
 

   

    此题用的方法巧妙,深搜加剪枝,如果输入N是奇数的话,由于起点从1开始,那么1-N之间一共有N / 2个偶数,N / 2 + 1个奇数,也就是奇数的个数比偶数多一个,那么把这N个数排成一个环,根据鸽巢原理,必然有两个奇数是相邻的,而两个奇数之和是偶数,偶数不是素数,所以我们得出结论,如果输入N是奇数的话,没有满足条件的排列。这样当N是奇数的时候,直接返回可。如果1-N之间每个数输入的几率相同,这个判断可以减少一半的计算量。再扩展一下,可以发现,任何一个满足条件的排列都有一个共同点:相邻的两个数奇偶性必然不同,原因是:两个奇数之和或者两个偶数之和都是偶数,而偶数一定不是素数,所以在选取当前元素的时候,比较一下它和前一个元素的奇偶性。再做决定,可以减少一部分计算量。由 于奇数 + 偶数 = 奇数, 而奇数的二进制表示中,最低位是1, 所以有下面的代码, 其中curValue是当前值, a[lastIndex]是前一个值.


#include<stdio.h>#include<stdlib.h>int prime[38]{  //巧妙的应用 0,0,1,1,0,1,0,1,0,0,0,1,0,1,0,0,0,1,0,1,0,0,0,1,0,0,0,1,0,1,0,1,0,0,0,0,0,1};bool isok(int a[], int lastIndex, int curValue){//if( lastIndex < 0 )//完全没必要判断,因为不可能小于零 //return true;if(!prime[a[lastIndex]+curValue])  //判断相邻两个数的和是否为素数 return false;if(!((a[lastIndex]+curValue)&1))  //判断相邻两个数的奇偶性 return false;for(int i=0; i<=lastIndex; ++i){  //判重 if(a[i]==curValue)return false;}return true;}void output(int a[], int n){for(int i=0; i<=n-1; ++i){if(i==n-1)printf("%d",a[i]);else printf("%d ",a[i]);}printf("\n");}void cyclePrime(int a[], int n, int k){if(n&1)return;if(k==n){if(prime[a[0]+a[n-1]])  //并且首尾也满足相加为素数,输出 output(a,n);}else{for(int i=2;i<=n;++i){a[k]=i;if(isok(a,k-1,i))cyclePrime(a,n,k+1);}}}int main(){int n,m=0;while(scanf("%d",&n)==1){int a[25];a[0]=1;printf("Case %d:\n",++m);cyclePrime(a,n,1);printf("\n");}return 0;}



0 0
原创粉丝点击