题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1560
题目大意:给出n个字符串,让你找一个字符串使得这n个字符串都是它的子串,求最小长度。
解题思路:迭代加深搜索,迭代加深搜索,就是限制DFS的深度deep,若搜不到答案,则加深深度,重新搜索,这样就防止了随着深度不断加深而进行的盲目搜索。这题的迭代深度deep以这n个子串中的最长长度作为起点,不断+1,知道找到符合条件的字符串。每次DFS的时候,都要判断一下,当前的深度+最少还有加深的深度是否大于限制的长度,若是,则返回上一层。
代码:
1 #include<cstdio> 2 #include<iostream> 3 #include<cstring> 4 #include<queue> 5 #include<string> 6 using namespace std; 7 typedef long long LL; 8 const int inf=0x3f3f3f3f; 9 10 int n,deep,ans; 11 char DNA[5]="ACGT"; 12 char str[10][10]; 13 14 int Max(int a,int b){ 15 return a>b?a:b; 16 } 17 18 void dfs(int index,int len[]){ 19 if(ans!=-1) 20 return; 21 int h=0;//接下来至少还要增加的字符长度 22 for(int i=1;i<=n;i++) 23 h=Max(h,strlen(str[i])-len[i]); 24 if(h==0){ 25 ans=index; 26 return; 27 } 28 if(h+index>deep)//当前深度+预测最小深度>限制深度 29 return; 30 int pos[10]={0}; 31 for(int i=0;i<4;i++){ 32 bool flag=false; 33 for(int j=1;j<=n;j++){ 34 if(str[j][len[j]]==DNA[i]){ 35 flag=true; 36 pos[j]=len[j]+1; 37 } 38 else 39 pos[j]=len[j]; 40 } 41 if(flag&&index+1<=deep)//剪枝,!flag说明无论加什么都无法使n个字符串都为子串 42 dfs(index+1,pos); 43 } 44 } 45 46 int main(){ 47 int t; 48 scanf("%d",&t); 49 while(t--){ 50 scanf("%d",&n); 51 int mlen=0;//最大子串长度 52 for(int i=1;i<=n;i++){ 53 scanf("%s",str[i]); 54 mlen=Max(strlen(str[i]),mlen); 55 } 56 57 int pos[10]={0};//n个字符串当前匹配到的位置 58 deep=mlen; 59 ans=-1; 60 while(1){ 61 dfs(0,pos); 62 if(ans!=-1) 63 break; 64 deep++; 65 } 66 printf("%d ",ans); 67 } 68 return 0; 69 }