题目链接:

http://acm.hdu.edu.cn/showproblem.php?pid=1016


(经典的剪枝搜索)

题意:

就是求1~n的一个环(首尾衔接,顺序打乱),使得相邻的两个元素之和为一个素数

题解1:

用C++中得STL生成全排列,超时!!!!

#include <cstdio>  #include <algorithm>  using namespace std;    int A[30];  bool prime[50];  bool is_prime(int n)  {      for (int i = 2; i*i <= n; i++)      {          if (!(n % i))          {              return 0;          }      }      return 1;  }    int main()  {      //freopen("input.txt","r",stdin);      for (int i = 0; i < 50; i++)      {          prime[i] = is_prime(i);      }      int N;      int nCase = 0;      while (~scanf("%d",&N))      {          printf("Case %d:\n",++nCase);          for (int i = 0; i < N; i++)              A[i] = i+1;          do          {              int ok = 1;              for (int i = 0; i < N-1; i++)              {                  if (!prime[A[i] + A[i+1]])                  {                      ok = 0;                      break;                  }              }                if (ok && prime[A[0]+A[N-1]])              {                  printf("%d",A[0]);                  for (int i = 1; i < N; i++)                  {                      printf(" %d",A[i]);                  }                  printf("\n");              }          }          while (next_permutation(A+1,A+N));          printf("\n");      }  }  

解法2:

递归搜索(+剪枝)

(一个PE搞了我好半天,本以为这个题跟Uva的一模一样......

Uva原文链接:

http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&category=24&page=show_problem&problem=465)

#include <cstdio>  #include <cstring>  using namespace std;    bool vis[50],prime[50];    bool is_prime(int n)  {      for (int i = 2; i*i <= n; i++)          if (!(n % i))              return 0;      return 1;  }  void init()  {      for (int i = 0; i < 50; i++)          prime[i] = is_prime(i);  }    void dfs(int *A,int cur,int n)  {      if (cur == n && prime[A[0] + A[n-1]])      {          printf("%d",A[0]);          for (int i = 1; i < n; i++)              printf(" %d",A[i]);          printf("\n");      }      else      {          for (int i = 2; i <= n; i++)          {              if (!vis[i] && prime[i + A[cur-1]])              {                  A[cur] = i;//尝试在*A中填入各种数                  vis[i] = 1;                  dfs(A,cur+1,n);                  vis[i] = 0;//记得一定得改回来(回溯常用技巧!!!)              }          }      }  }    int main()  {      init();  //    freopen("input.txt","r",stdin);      memset(vis,0,sizeof(vis));      int A[30] = {1};      int N;      int nCase = 1;      while (~scanf("%d",&N))      {          /*                  if (nCase > 1)                     printf("\n");          */          printf("Case %d:\n",nCase++);          dfs(A,1,N);          printf("\n");//如果是Uva上的素数环的话,就用上面的/*if (nCase > 1) printf("\n");*/      }  }