题目链接:
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原文链接:
#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");*/ } }