题目传送门:1002. Anti-prime Sequences
思路:
本题使用了dfs深度优先搜索(回溯法),用递归的形式实现。
一开始见到3s的时间竟然傻乎乎的跑去用回溯法按照字典序生成全排列,然后一个个的去判断是否是anti-prime,直接被TLE拍死。
后来才突然醒悟在搜索到某个数字时可以利用2到degree的相邻数字和不是素数这个性质进行大量剪枝才搞定。
这里选择了vector作为容器是为了能同时实现对元素的快速下标访问于在某一特定位置的增删元素。
用一个vector result存储生成的anti-prime sequence,然后将n~m这些数字一个一个的插进result中,插入时判断是否满足序列性质。如果迭代完整个numbers里面的元素都没找到能插入的元素,则删掉最后一个插入的元素,回溯到前面的情况。用全局变量bool unsolved判断是否已经找到序列,找到之后后面的搜索可以不用进行。
代码:
1 #include<iostream> 2 #include<vector> 3 #include<memory.h> 4 using namespace std; 5 6 const int MAX=10000; 7 8 int n,m,d; 9 vector<int>numbers,result; 10 bool prime[MAX]; 11 bool unsolved=true; 12 13 void generate_prime_list(); 14 void dfs_search_sequence(); 15 bool can_be_insert(int new_entry); 16 17 int main(){ 18 generate_prime_list(); 19 while(cin>>n>>m>>d&&(n!=0||m!=0||d!=0)){ 20 numbers.clear(); 21 result.clear(); 22 unsolved=true; 23 for(int i=n;i<=m;i++) 24 numbers.push_back(i); 25 dfs_search_sequence(); 26 if(unsolved) 27 cout<<"No anti-prime sequence exists."<<endl; 28 } 29 return 0; 30 } 31 void generate_prime_list(){ 32 memset(prime,true,sizeof(prime));//assume all are prime first. 33 for(int i=2;i<=100;++i){ 34 if(prime[i]){ 35 for(int j=2;j*i<MAX;++j){//times of a prime number can not be prime. 36 prime[j*i]=false; 37 } 38 } 39 } 40 } 41 void dfs_search_sequence(){ 42 //Post:If the anti-prime sequence exist,the lexicographically first will be printed. 43 //Uses:the method of vector,the function dfs_search_sequence recursively,the function can_be_inserted. 44 if(unsolved){ 45 int size_of_numbers=numbers.size(),size_of_result=result.size(); 46 if(size_of_result==m-n+1){//already find the full sequence 47 unsolved=false; 48 for(int i=0;i<size_of_result-1;i++) 49 cout<<result[i]<<','; 50 cout<<result[size_of_result-1]<<endl; 51 } 52 else{ 53 for(int i=0;i<size_of_numbers;i++){ 54 int entry=numbers[i]; 55 if(can_be_insert(entry)){ 56 result.push_back(entry); 57 numbers.erase(numbers.begin()+i); 58 dfs_search_sequence(); 59 //move back 60 numbers.insert(numbers.begin()+i,entry); 61 result.pop_back(); 62 } 63 } 64 } 65 } 66 } 67 bool can_be_insert(int new_entry){ 68 //Post:If the new_entry can be inserted in the back of the result and remain the anti-prime 69 // property,return true.Otherwise return false. 70 int size=result.size(),sum=new_entry; 71 for(int i=size-1;i>size-d&&i>=0;i--){ 72 sum+=result[i]; 73 if(prime[sum]) 74 return false; 75 } 76 return true; 77 }