HDU-#1560 DNA sequence(迭代加深搜)
题目大意:给出n个DNA序列,求包含这n个子序列的公共序列的最短长度。
解题思路:由于每次搜索长度未知,因此可以采用迭代加深搜,先将最长的子序列长度作为初始的深搜长度,之后满足条件则进行+1迭代。直到搜索完所有子序列,然后输出deep。这里的迭代加深搜与IDA*很类似了,如果将下面的check_lenth()函数作为IDA*的h()代价函数,就是IDA*算法了,但是这样的效果应该不是很好,应该可以更加优化代价函数,感兴趣的可以尝试下。详见code。
code:
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> using namespace std; char DNA[]={"ACGT"}; int n,t,deep; int pos[10]; bool flag; struct node{ char str[6]; int lenth; }a[10]; int check_lenth(){ int check=0; for(int i=1;i<=n;i++) check=max(check,a[i].lenth-pos[i]); return check; } bool DFS(int k){ int check=check_lenth(); //记录当前还可以使用的最大长度 if(check+k>deep) return false; //如果已经使用长度+还可以使用的最长长度大于迭代深度,则返回 if(check==0) return true; for(int i=0;i<4;i++){ int temp=0; int tmp[10]; //中间数组,用于保存当前状态,用于还原信息 for(int j=1;j<=n;j++) //记录当前状态信息 tmp[j]=pos[j]; for(int j=1;j<=n;j++){ //进行列向扫描 if(a[j].str[pos[j]]==DNA[i]){ //进行匹配 temp=1; pos[j]++; } } if(temp){ //有符合的则向下搜索 if(DFS(k+1)) return true; //进行迭代 else for(int j=1;j<=n;j++) //没有匹配则还原之前的状态 pos[j]=tmp[j]; } } return false; } int main(){ scanf("%d",&t); while(t--){ int maxx=-1; scanf("%d",&n); for(int i=1;i<=n;i++){ scanf("%s",&a[i].str); a[i].lenth=strlen(a[i].str); pos[i]=0; //访问位置置0 maxx=max(maxx,a[i].lenth); } deep=maxx; //获取序列中最大长度作为初始的迭代深度 while(1){ if(DFS(0)) break; deep++; //每次迭代深度++ } printf("%d ",deep); } return 0; }