ZOJ 1457 题解
题目链接:http://acm.zju.edu.cn /show_problem.php?pid=1457
寒啊……居然差不多把错误都犯遍了,OLE->RTE->TLE->WA->PE->AC,做了好久,而且还是传说中的简 单题,这个题目就是简单的回溯,剪枝也相当简单,那我怎么就……
题目的意思也比较好理解,就是要求把一个序列排成一个环(又是序列,呵呵),当然这个序列是从1,2,3,4,5,....,n,要求这个序列的性质是相 邻两个数的和是一个素数。要求输出满足这个性质环的全部组合。开始的时候也不知道怎么了居然出现OLE,寒啊。。。出现TLE的原因是没有处理奇数和偶 数,实际上,如果给出的n是奇数就可以不做回溯了,因为这个时候奇数的个数比偶数多一个,不论怎么排列,至少有一对相邻的数都是奇数,这两个数的和不可能 是素数了,这样就可以大大加快速度了。不过我的程序的0.78s与前面的0.23s比起来还是慢啊
题目的思路比较直接,就是回溯,给出各种情况,当出现相邻两个数的和不是素数的时候剪掉。
不管怎样,代码如下:in C++
代码
1 #include<iostream>
2 #include<cstdio>
3 using namespace std;
4
5 int isprime[40] ;
6 int p[21] ;
7 int visited[21] ;
8
9 void perm(int k , int n)
10 {
11 for(int i = 2 ; i <= n ; i ++)
12 {
13 if(!visited[i] && isprime[p[k - 1] + i])
14 {
15 visited[i] = 1 ;
16 p[k] = i ;
17 perm(k + 1 , n) ;
18 visited[i] = 0;
19 }
20 }
21 if(k == n + 1 && isprime[p[k - 1] + 1])
22 {
23 for(int i = 1 ; i <= n ; i ++)
24 {
25 if(i != 1)
26 printf(" ");
27 printf("%d",p[i]);
28 }
29 printf("\n");
30 return ;
31 }
32 }
33 int main()
34 {
35 int cases = 0 ;
36 int n ;
37
38 memset(isprime, 0, 40);
39 isprime[2] = isprime[3] = isprime[5] = isprime[7] = isprime[11] = isprime[13] = isprime[17] = isprime[19]
40 = isprime[23] = isprime[29] = isprime[31] = isprime[37] = 1 ;
41 while(scanf("%d",&n) != EOF)
42 {
43 printf("Case %d:\n",++cases);
44 if(n % 2 == 0)
45 {
46 memset(visited , 0 , n + 1) ;
47 p[1] = 1 ;
48 perm(2 , n) ;
49
50 }
51 printf("\n");
52 }
53
54 return 0;
55 }
56
2 #include<cstdio>
3 using namespace std;
4
5 int isprime[40] ;
6 int p[21] ;
7 int visited[21] ;
8
9 void perm(int k , int n)
10 {
11 for(int i = 2 ; i <= n ; i ++)
12 {
13 if(!visited[i] && isprime[p[k - 1] + i])
14 {
15 visited[i] = 1 ;
16 p[k] = i ;
17 perm(k + 1 , n) ;
18 visited[i] = 0;
19 }
20 }
21 if(k == n + 1 && isprime[p[k - 1] + 1])
22 {
23 for(int i = 1 ; i <= n ; i ++)
24 {
25 if(i != 1)
26 printf(" ");
27 printf("%d",p[i]);
28 }
29 printf("\n");
30 return ;
31 }
32 }
33 int main()
34 {
35 int cases = 0 ;
36 int n ;
37
38 memset(isprime, 0, 40);
39 isprime[2] = isprime[3] = isprime[5] = isprime[7] = isprime[11] = isprime[13] = isprime[17] = isprime[19]
40 = isprime[23] = isprime[29] = isprime[31] = isprime[37] = 1 ;
41 while(scanf("%d",&n) != EOF)
42 {
43 printf("Case %d:\n",++cases);
44 if(n % 2 == 0)
45 {
46 memset(visited , 0 , n + 1) ;
47 p[1] = 1 ;
48 perm(2 , n) ;
49
50 }
51 printf("\n");
52 }
53
54 return 0;
55 }
56