第七章素数环
在网上搜索了一下我的第一种方法应该是减枝的策略,回溯也是减枝的一种
#include <iostream> #include <cstdio> #include <algorithm> using namespace std; const int maxn=20; int ans[maxn]; int n; bool prime(int num) { if(num==2 || num==1) return true; for(int i=2;i<num;i++) if(num%i==0) return false; return true; } void solve(int cur) { if(cur==n) { if(ans[0]==1) { for(int i=0;i<n;i++) printf("%d ",ans[i]); printf("\n"); } return; } for(int i=1;i<=n;i++) { /* if(ans中不存在) if(如果是最后一个要判断两次) pass if(如果不是最后一个判断和前一个是否成立) pass */ int ok=1; for(int j=0;j<cur;j++) if(ans[j]==i) { ok=0; break; } if(ok) { if(cur==n-1) { if(prime(i+ans[0]) && prime(i+ans[cur-1])) { ans[cur]=i; solve(cur+1); } } else { if(cur==0) { ans[cur]=i; solve(cur+1); } else { if(prime(i+ans[cur-1])) { ans[cur]=i; solve(cur+1); } } } } } } int main() { cin>>n; solve(0); return 0; }
利用stl全排列,这种方法有个缺点就是当情况比较多时会很慢
#include <iostream> #include <cstdio> #include <algorithm> using namespace std; const int maxn=20; int ans[maxn]; int n; bool prime(int num) { if(num==2 || num==1) return true; for(int i=2;i<num;i++) if(num%i==0) return false; return true; } void solve() { for(int i=0;i<n;i++) ans[i]=i+1; do { if(ans[0]==1) { int ok=1; for(int i=1;i<n;i++) { if(i==n-1) if(!prime(ans[i]+ans[i-1]) || !prime(ans[i]+ans[0])) ok=0; if(i!=n-1) if(!prime(ans[i]+ans[i-1])) ok=0; } if(ok) { for(int i=0;i<n;i++) printf("%d ",ans[i]); printf("\n"); } } else break; }while(next_permutation(ans,ans+n)); } int main() { cin>>n; solve(); return 0; }
回溯法实现,还可以给素数打个表
#include <iostream> #include <cstdio> #include <algorithm> #include <cmath> using namespace std; const int maxn=20; int ans[maxn]; int n; int vis[maxn]; bool is_prime(int num) { if(num==2 || num==1) return true; for(int i=2;i<num;i++) if(num%i==0) return false; return true; } void solve(int cur) { if(cur==n) { for(int i=0;i<n;i++) printf("%d ",ans[i]); printf("\n"); } else { for(int i=2;i<=n;i++) { if(!vis[i] && is_prime(ans[cur-1]+i)) { ans[cur]=i; vis[i]=1; solve(cur+1); vis[i]=0; } } } } int main() { cin>>n; ans[0]=1; solve(1); return 0; }
Yosoro