http://acm.hdu.edu.cn/showproblem.php?pid=1016
题意:输入n,代表有一个包含n个节点的环,在环中的节点中填入1,2...n-1,n,要求填入的数与左边的数之和,与右边的数之和,都为素数
输出所有符合要求的环(第一个数总为1)
用DFS模拟,从第2位到第n位依次选取一个与上一个选取的数之和为素数的数
直到选取完第n个数,判断第n个数和1之和是否为素数,是则输出,否则不进行操作,判断完毕返回上一层
直到遍历完所有情况
*:因为素数必然是奇数,所以一条符合要求的素数环每两个相邻的数肯定是一奇一偶
然而当n为奇数且不等于1时,不管怎么排列,总会出现相邻的两个的数同为奇数或同为偶数,使得两者之和必是偶数,不是素数
所以,当n为奇数且不等于1时,可以不用进行处理,剪枝50%
**:但是杭电的数据里n貌似都是偶数,特判n和不特判n的时间花费都差不多,所以并没什么卵用
# include <stdio.h> # include <math.h> # include <string.h> int Prime[50], Ring[25], n; bool Flag[25]; bool IsPrime(int num) { int t = sqrt(double(num)); for(int i = 3; i <= t; i++) if(num % i == 0) return false; return true; } void DFS(int Depth) { if(Depth == n + 1)//若以全部选择完毕 { if(Prime[Ring[Depth - 1] + 1])//查看最后一个和第一个之和是否是素数 { printf("1"); for(int i = 2; i <= n; i++) printf(" %d", Ring[i]); printf("\n"); } return ; } for(int i = 2; i <= n; i++) { if(!Flag[i] && Prime[i + Ring[Depth - 1]])//i与上一个选的数之和是否是素数 { Ring[Depth] = i; Flag[i] = true;//每选取一个数就将其标记 DFS(Depth + 1); Flag[i] = false;//搜索完选取该数之后的所有可能后,取消标记 } } } int main() { for(int i = 3; i < 50; i += 2) Prime[i] = 1; Prime[2] = 1; for(int i = 3; i < 50; i += 2) { if(IsPrime(i)) { for(int j = i * 2; j < 50; j += i) Prime[j] = 0; }else Prime[i] = 0; }//素数打表 int Case = 0; while(scanf("%d",&n) != EOF) { printf("Case %d:\n", ++Case); if(n == 1) printf("1\n"); else if(n % 2 == 0) { memset(Flag, false, sizeof(Flag)); Flag[1] = true; Ring[1] = 1;//第一个始终为1 DFS(2); } printf("\n"); } return 0; }
时间: 2024-10-02 18:25:28