杭电 Prime Ring Problem


解题思路:

题目是一道很典型的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//

 代码如下

 

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  }

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值