一道IDA*题目。
意思就是求一个最短的碱基序列使得所有输入的碱基序列都是这个序列的子序列。
很容易想到我们可以先定义一个深度,然后依次放入ATGC,直到达到深度为止。
如果达到深度并且每个字符串都走到了最后,那么就可以判定这个深度是可行的,意味着我们需要维护一个已经匹配的位置的数组。
其次还能剪枝,当当前的位置加上未匹配完的字符串中剩余位置数的最大值大于深度了,我们认为这个方案可以直接剪掉。
#include<cstdio>
#include<queue>
#include<stack>
#include<map>
#include<list>
#include<vector>
#include<string>
#include<iostream>
#include<ctime>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<cstdlib>
using namespace std;
const int MAXN = 10;
char str[MAXN][MAXN];
int len[MAXN];
int depth, n;
char dna[4]={'A','T','C','G'};
bool ida(int now, int pos[MAXN]){
int maxLen = 0;
for (int i = 0; i < n; ++i) {
maxLen= max(maxLen, len[i]-pos[i]);
}
if (now-1+maxLen>depth){
return false;
}
if (now==depth+1 && maxLen==0){
return true;
}
int tmp[MAXN];
for (int i = 0; i < 4; ++i) {
for (int j = 0; j < n; ++j) {
if (str[j][pos[j]]==dna[i]){
tmp[j]=pos[j]+1;
}else{
tmp[j]=pos[j];
}
}
if (ida(now+1,tmp)){
return true;
}
}
return false;
}
int main() {
int t, pos[MAXN];
scanf("%d",&t);
while (t--){
scanf("%d",&n);
depth=0;
for (int i = 0; i < n; ++i) {
scanf("%s", str[i]);
len[i]= strlen(str[i]);
depth= max(depth,len[i]);
}
memset(pos,0, sizeof(pos));
while (true){
memset(pos,0,sizeof(pos));
if (ida(1, pos)){
printf("%d\n",depth);
break;
}
depth++;
}
}
return 0;
}