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, 040);
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 


posted on 2010-02-05 01:51  vivy  阅读(288)  评论(0编辑  收藏  举报