解题思路:
题目是一道很典型的dfs搜索题目,思路很清晰,很容易想到。想组成这个素数环,要有n步,而每步都有n-i(i是变动的)种可能,所以利用dfs深搜,并融合回溯法,这一步搜不到的话既返回至上一步进行。因为一点不能同时选择两次,所以要用标记这个点已经被选中,如果这一步搜索失败,那么要把这一步所标记的定点都复原,才能返回上一步进行搜索。
我没有在dfs里面直接判断素数,因为我觉得那样程序会慢,所以编写了一个求素数的函数,这样单独处理也可以防止乘法溢出的现象。另外要提到的是,搜索终止条件出了要搜索的补数达到要求以外,最后一个搜到的和第一个也要同时比较。
ps:最近一直在做 搜索,感觉剪枝是比较重要的,虽然这道题没有用上,但是必须要有剪枝的思想,不然和暴力没什么区别,题目只要不是水题,都不会过的。
//题目链接:http://acm.hdu.edu.cn/webcontest/contest_showproblem.php?pid=1004&ojid=0&cid=4532&hide=0//
代码如下:
C语言:
高亮代码由发芽网提供
01
#include<stdio.h>
02 #include<string.h>
03 #include<math.h>
04 int n , vis1 = 1;
05 int count = 2;
06 bool vis [ 20 ];
07 int primecircle [ 20 ];
08 int num [ 20 ];
09 int is_prime( int x)
10 {
11 int i;
12 int m;
13 m = floor( sqrt( x + 0.5));
14 for( i = 2; i <= m; i ++)
15 {
16 if( x % i == 0)
17 return 0;
18 }
19 return 1;
20 }
21 void dfs( int k)
22 {
23 int i;
24 int flag = 0;
25 if( k ==n && is_prime( primecircle [ k ] + primecircle [ 1 ]))
26 {
27 vis1 = 1;
28 for( int j = 1; j <=n; j ++)
29 {
30 if( vis1)
31 {
32 printf( "%d" , primecircle [ j ]);
33 vis1 = 0;
34 }
35 else
36 printf( " %d" , primecircle [ j ]);
37 }
38 printf( " \n ");
39 }
40 else
41 for( i = 1; i <n; i ++)
42 {
43 //if(((k+num[i])%2!=0)&&(vis[i]==1))
44 flag = is_prime( primecircle [ k ] + num [ i ]);
45 if( flag == 1 && vis [ i ] == 1)
46 {
47 //vis[k]=0;
48 vis [ i ] = 0;
49 primecircle [ count ++ ] = num [ i ];
50 dfs( k + 1);
51 //vis[k]=1;
52 vis [ i ] = 1;
53 count --;
54
55 }
56 }
57 }
58 int main()
59 {
60 int xuran = 1;
61 int i , j , k;
62 int temp;
63 primecircle [ 1 ] = 1;
64 while( scanf( "%d" , &n) != EOF)
65 {
66 memset( vis , 1 , sizeof( vis));
67 temp = 1;
68 for( j = 0; j <n; j ++)
69 {
70 num [ j ] = temp ++;
71 }
72 printf( "Case %d:" , xuran);
73 printf( " \n ");
74 dfs( 1);
75 printf( " \n ");
76 xuran ++;
77 }
78 return 0;
79 }
02 #include<string.h>
03 #include<math.h>
04 int n , vis1 = 1;
05 int count = 2;
06 bool vis [ 20 ];
07 int primecircle [ 20 ];
08 int num [ 20 ];
09 int is_prime( int x)
10 {
11 int i;
12 int m;
13 m = floor( sqrt( x + 0.5));
14 for( i = 2; i <= m; i ++)
15 {
16 if( x % i == 0)
17 return 0;
18 }
19 return 1;
20 }
21 void dfs( int k)
22 {
23 int i;
24 int flag = 0;
25 if( k ==n && is_prime( primecircle [ k ] + primecircle [ 1 ]))
26 {
27 vis1 = 1;
28 for( int j = 1; j <=n; j ++)
29 {
30 if( vis1)
31 {
32 printf( "%d" , primecircle [ j ]);
33 vis1 = 0;
34 }
35 else
36 printf( " %d" , primecircle [ j ]);
37 }
38 printf( " \n ");
39 }
40 else
41 for( i = 1; i <n; i ++)
42 {
43 //if(((k+num[i])%2!=0)&&(vis[i]==1))
44 flag = is_prime( primecircle [ k ] + num [ i ]);
45 if( flag == 1 && vis [ i ] == 1)
46 {
47 //vis[k]=0;
48 vis [ i ] = 0;
49 primecircle [ count ++ ] = num [ i ];
50 dfs( k + 1);
51 //vis[k]=1;
52 vis [ i ] = 1;
53 count --;
54
55 }
56 }
57 }
58 int main()
59 {
60 int xuran = 1;
61 int i , j , k;
62 int temp;
63 primecircle [ 1 ] = 1;
64 while( scanf( "%d" , &n) != EOF)
65 {
66 memset( vis , 1 , sizeof( vis));
67 temp = 1;
68 for( j = 0; j <n; j ++)
69 {
70 num [ j ] = temp ++;
71 }
72 printf( "Case %d:" , xuran);
73 printf( " \n ");
74 dfs( 1);
75 printf( " \n ");
76 xuran ++;
77 }
78 return 0;
79 }