Problem Description
The twenty-first century is a biology-technology developing century. We know that a gene is made of DNA. The nucleotide bases from which DNA is built are A(adenine), C(cytosine), G(guanine), and T(thymine). Finding the longest common subsequence between DNA/Protein sequences is one of the basic problems in modern computational molecular biology. But this problem is a little different. Given several DNA sequences, you are asked to make a shortest sequence from them so that each of the given sequence is the subsequence of it.
For example, given "ACGT","ATGC","CGTT" and "CAGT", you can make a sequence in the following way. It is the shortest but may be not the only one.
Input
The first line is the test case number t. Then t test cases follow. In each case, the first line is an integer n ( 1<=n<=8 ) represents number of the DNA sequences. The following k lines contain the k sequences, one per line. Assuming that the length of any sequence is between 1 and 5.
Output
For each test case, print a line containing the length of the shortest sequence that can be made from these sequences.
Sample Input
1 4 ACGT ATGC CGTT CAGT
Sample Output
8
题意:
从n个串中找出一个最短的公共串,,该公共串对于n个字符串不要求连续,即只要保持相对顺序就好。
思路:
用迭代加深搜索,所谓迭代加深搜索,就是限制DFS的深度,若搜不到答案,则加深深度,重新搜索,这样就防止了随着深度不断加深而进行的盲目搜索,而且,对于这种求最短长度之类的题目,只要找到可行解,即是最优解了。同时注意剪枝,每次DFS的时候,都要判断一下,当前的深度+最少还有加深的深度是否大于限制的长度,若是,则退回上一层状态。
#include
using namespace std;
char str[10][10];//记录n个字符串
int n, ans, deep, Size[10];
char DNA[4] = { 'A','C','G','T' };//4种可能性
void dfs(int cnt,int len[]) {
if (cnt > deep)return;//大于了最大深度
int maxx = 0;//预计还要匹配的字符串的最大长度
for (int i = 0; i < n; ++i) {
int t = Size[i] - len[i];
if (t > maxx)
maxx = t;
}
if (maxx == 0) {//条件全部满足即为最优解
ans = cnt; return;
}
if (cnt + maxx > deep)return;
for (int i = 0; i < 4; ++i) {
int pos[10], flag = 0;
for (int j = 0; j < n; j++)
{
if (str[j][len[j]] == DNA[i])
{
flag = 1;
pos[j] = len[j] + 1;
}
else
pos[j] = len[j];
}
if (flag)
dfs(cnt + 1, pos);
if (ans != -1)
break;
}
}
int main() {
int T;
cin >> T;
while (T--) {
cin >> n;
int maxn = 0;
for (int i = 0; i < n; ++i) {
cin >> str[i];
Size[i] = strlen(str[i]);
if (Size[i] > maxn)
maxn = Size[i];
}
ans = -1; deep = maxn;
int pos[10] = { 0 };//记录n个字符串目前匹配到的位置
while (1) {
dfs(0, pos);
if (ans != -1)break;
++deep;
}
cout << ans << endl;
}
return 0;
}