题目大意:给出n个DNA序列,求包含这n个子序列的公共序列的最短长度。
解题思路:由于每次搜索长度未知,因此可以采用迭代加深搜,先将最长的子序列长度作为初始的深搜长度,之后满足条件则进行+1迭代。直到搜索完所有子序列,然后输出deep。这里的迭代加深搜与IDA*很类似了,如果将下面的check_lenth()函数作为IDA*的h()代价函数,就是IDA*算法了,但是这样的效果应该不是很好,应该可以更加优化代价函数,感兴趣的可以尝试下。详见code。
题目来源:http://acm.hdu.edu.cn/showproblem.php?pid=1560
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\n",deep);
}
return 0;
}