追溯法应用举例2-困难的串
Posted savennist
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了追溯法应用举例2-困难的串相关的知识,希望对你有一定的参考价值。
题目选自UVA-129:https://vjudge.net/problem/UVA-129
在刘汝佳的紫书中,曾经强调利用八皇后中的思想,借助字符串的后缀来生成数据。不需要刻意验证当下递归中所添加的字母是否同以后添加的字母满足题目关系。这一点与八皇后代码中按照每行或每列逐一递归的思想是相吻合的。在我的代码中,对于每一次添加的字符,都需要与前方已经添加好的相邻的字符组合并对比,以此来检查它是否满足了简单的串的定义。借助一维数组,如果此时需要填充的位置下标是cur,而填充的字母与前面相邻的字母组成了长度为k的子串,那么对比与该子串相邻的前方的长度同样为k的子串即可。(很明显,k==1表示对比cur处讨论的字符与cur-1处的字符的关系)。
代码如下:
1 #include<cstdio> 2 #include<cstring> 3 using namespace std; 4 int n,L; 5 int aim[100];//使用数字代表字母,借鉴了紫书里的想法 6 int allok=0; 7 int cnt; 8 int strpre(int* s,int* c,int lenth) 9 { 10 for(int i=0;i<lenth;i++) 11 if(s[i]!=c[i])return 0; 12 return 1; 13 } 14 15 int outer(int cur)//按照题目格式输出 16 { 17 int lenth=cur; 18 int gnum=0; 19 int per=0; 20 int start=0; 21 for(int i=0;i<cur;i++) 22 { 23 if(start&&per==0) 24 { 25 if(gnum==15){printf(" ");gnum=0;}//经过实验,发现是15而非16 26 else {gnum++;printf(" ");} 27 } 28 start=1; 29 printf("%c",aim[i]+‘A‘); 30 per++; 31 per=per%4; 32 } 33 printf(" %d ",lenth); 34 return 0; 35 } 36 37 int solve(int cur) 38 { 39 if(allok)return 0; 40 if(cnt==n) 41 { 42 outer(cur); 43 allok=1; 44 return 0; 45 } 46 for(int i=0;i<L;i++) 47 { 48 if(cur==0) 49 { 50 aim[0]=i; 51 cnt++; 52 solve(1); 53 continue; 54 } 55 //if(aim[cur-1]==i)continue;//该句的作用已经被下面的for循环所取代 56 aim[cur]=i; 57 int ok=1; 58 for(int k=1;2*k<=cur+1;k++)//后缀字符的组合对比 59 { 60 int* temp1=&aim[cur]-(k-1); 61 int* temp2=temp1-k; 62 if(strpre(temp1,temp2,k)) 63 { 64 ok=0; 65 break; 66 } 67 } 68 if(ok){cnt++;solve(cur+1);} 69 } 70 return 0; 71 } 72 73 int main() 74 { 75 while(scanf("%d%d",&n,&L)&&n&&L) 76 { 77 allok=0;//注意初始化 78 cnt=0; 79 memset(aim,0,sizeof(aim));//这句并没有什么用处 80 solve(0); 81 } 82 return 0; 83 }
以上是关于追溯法应用举例2-困难的串的主要内容,如果未能解决你的问题,请参考以下文章