NYOJ 488 素数环
2013-11-11 00:40
302 查看
题目:
http://acm.nyist.net/JudgeOnline/problem.php?pid=488
思路:
“全排列”思想。
以“6”为例,
1 4 3 2 5 6 1 6 5 2 3 4
1.上面两组可以构成素数环,所谓“环”, 即循环,只取出全排列中以1开头的那部分就可以,换句话说,对2-6进行全排列就可以了。
2.“素数”,每两个的和必须是素数,注意素数的判定(前面整理过了);
3.“2-6”排列中的第一个数,要和1相加,判断一下和是否是素数;
4.“环”, 首尾要连接起来,也要判定是否构成素数;
实现:
使用标记数组B,记录当前遍历到的数是否被选过(少用了一个判断,即else里面只有一个循环,时间明显提高);
改进的程序中,else里面只有一个循环,比之前提高了效率;
只有一个1的时候,也构成一个素数环;
当输入的数是除1之外的素数的时候,不用进入递归去判断,直接输出No answer就可以了, 同时也提高了时间效率(当初也就是改了这里,改正了超时的错误);
#include<stdio.h> #include<string.h> void Primes(); void PrimeCirculer(int n, int cur); bool number[40] = {0}; //素数标记数组, 0 为素数,1为非素数; bool B[200] = {0, 1}; //标记数组; int A[20] = {0, 1}; int flag = 0; //标记No Answer的情况; int main(void) { int n, i = 1; //i记录case个数; Primes(); while(scanf("%d", &n), n != 0) { printf("Case %d:\n", i++); if(n != 1 && n % 2 != 0) //素数单独拿出来,减少判断; { printf("No Answer\n"); } else { PrimeCirculer(n, 2); //类似于只输出以1开头的全排列的一部分, 所以从2开始, 输出2-n的部分全排列,将下标为1的位置置1; if(flag == 0) printf("No Answer\n"); memset(A, 0, sizeof(A)); memset(B, 0, sizeof(B)); A[1] = 1; B[1] = 1; flag = 0; } } return 0; } void Primes() //素数标记成0, 否则标记为1; { int i, j; for(i = 2; i * i < 40; i++) { if(number[i] == 0) { for(j = i + i; j < 40; j = j + i) { number[j] = 1; } }//if }//for } void PrimeCirculer(int n,int cur) { int i, j; if(cur == n + 1 )// { if(number[ A[1] + A ] == 0) { for(i = 1; i <= n; i++) printf("%d ", A[i]); flag = 1;//** printf("\n"); }//if } else { for(i = 2; i <= n; i++) { if(B[i] == 0 && number[ A[cur - 1] + i ] == 0) { A[cur] = i; B[i] = 1; PrimeCirculer(n, cur + 1); B[i] = 0; } }//for }//else }
相关文章推荐
- NYOJ 488 素数环 注意细节问题
- nyoj 488 素数环
- nyoj 488 素数环(深搜)
- nyoj488(素数环)
- NYOJ 488 素数环(DFS)
- NYOJ 488 素数环 (深搜DFS)
- NYOJ488 素数环 【回溯】+【预处理】
- nyoj 488 素数环 【dfs】
- nyoj 488 素数环
- NYOJ_488题 素数环 的经验之谈
- NYOJ 488 素数环(深搜)
- nyoj-488-素数环
- NYOJ488-素数环
- nyoj 488 素数环
- NYOJ 488 素数环(DFS)
- nyoj 488素数环 回溯dfs
- nyoj-488-素数环
- NYOJ ~ 488 ~ 素数环 (DFS+剪枝)
- NYOJ - 488 - 素数环(回溯法)
- NYOJ 488 - 素数环