UVA524 素数环 Prime Ring Problem
标签:搜索与回溯
题目:
从1到20这20个数摆成一个环,要求相邻的两个数的和是一个素数。
算法分析:
非常明显,这是一道回溯的题目。从1开始,每个空位有20种可能,只要填进去的数合法:与前面的数不相同;与左边相邻的数的和是一个素数。第20个数还要判断和第1个数的和是否素数。
算法流程:
1、数据初始化;
2、递归填数:判断第i个数填入是否合法;
A、如果合法:填数;判断是否到达目标(20个已填完):是,打印结果;不是,递归填下一个;
B、如果不合法:选择下一种可能;
题解:
#include <iostream> #include <cmath> using namespace std; bool b[21]={0}; int a[21]={0}; int search(int); int print(); bool pd(int,int); int main() { search(1); return 0; } int search(int t) { for (int i=1;i<=20;i++) if(pd(a[t-1],i)&&(!b[i])) { a[t]=i; b[i]=1; if(t==20) { if(pd(a[20],a[1])) print(); } else search(t+1); b[i]=0; } } int print() { for(int j=1;j<=20;j++) cout<<a[j]<<' '; cout<<endl; } bool pd(int x,int y) { int k=2; while(k<=sqrt(x+y)&&(x+y)%k!=0)k++; if(k>sqrt(x+y))return 1; else return 0; }
知识点:
- 素数筛法
void ifprime() { //打表法将1到40之间所有的素数用1标记放入数组中对应位置,其余数用0标记 for(int i=2;i<40;i++) prime[i]=1; prime[1]=0; for(int i=2;i<40;i++) for(int j=2*i;j<=40;j+=i) prime[j]=0; }
- 素数定义法
bool pd(int x,int y) { int k=2; while(k<=sqrt(x+y)&&(x+y)%k!=0)k++; if(k>sqrt(x+y))return 1; else return 0; }
错解:
忘记了1到20不能重复,搜索写的也有问题
//1到20素数环 #include <iostream> using namespace std; int a[21]; int nas[40]; int check() { //素数筛 for(int i=2;i<=40;i++)nas[i]=1; nas[1]=0; for(int i=2;i<40;i++) for(int j=2*i;j<40;j+=i) { nas[j]=0; } } int search(int k) { if(k==20) { for(int i=1;i<=20;i++) if(nas[a[1]+a[20]]) for(int j=1;j<=20;j++) cout<<a[j]; } for(int i=1;i<=20;i++) { if(nas[a[k]+i]) { a[k+1]=i; search(k+1); } a[k+1]=0; search(k); } } int main() { check(); for(int i=1;i<=20;i++) { a[1]=i; search(1); for(int j=1;j<=20;j++)a[j]=0; } return 0; }