HDU 1560 DNA sequence(DNA序列)
Time Limit: 15000/5000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Problem Description - 题目描述
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.
二十一世纪是生物技术突飞猛进的世纪。我们知道基因由DNA组成。构建DNA的核苷酸有A(腺嘌呤),C(胞嘧啶),G(鸟嘌呤)和T(胸腺嘧啶)。寻找DNA/蛋白质序列间的最长公共子序列是现代计算分子生物学的基本问题之一。然而这个问题有些许不同。给定若干DNA序列,你需要构建一个最短序列使得给定序列都是都是它的子序列。 比如。给定"ACGT","ATGC","CGTT"和"CAGT",你可以通过如下方式构建一个序列。最短序列不唯一。
CN
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.
第一行为测试用例的数量t。随后t个测试用例。
每个用例中第一行为一个整数n ( 1<=n<=8 ) 表示DNA序列的数量。
随后k行,每行一个序列。假定任意序列长度为1到5。
CN
Output - 输出
For each test case, print a line containing the length of the shortest sequence that can be made from these sequences.
对于每个测试用例,输出一行可构建序列的最短长度。
CN
Sample Input - 输入样例
1
4
ACGT
ATGC
CGTT
CAGT
Sample Output - 输出样例
8
题解
IDA* = (暴力DFS + 剪枝)*反反复复,所以问题在于怎么剪枝
如果用剩余待匹配序列的最大长度来剪枝……下面的数据就有问题(虽然HDU上并没有)
1
4
AAAA
CCCC
GGGG
TTTT
然后秉着不会做就百度的原则(逃
横着看有问题,竖着看?
统计每行ACGT的个数,然后在以此求各个ACGT最大的和,依次剪枝就比上面的方法科学多了……
代码 C++
#include <cstdio>
#include <cstring>
#include <algorithm>
int maxDeep, n, data[][];
int vle(int(&siz)[][]) {
int i, j, opt, len[];
memset(len, , sizeof len);
for (i = ; i < n; ++i) {
for (j = ; j < ; ++j) len[j] = std::max(len[j], siz[i][j]);
}
for (i = opt = ; i < ; opt += len[i++]);
return opt;
}
int DFS(int deep, int(&preW)[], int(&preSiz)[][]) {
int i = vle(preSiz), j, w[], siz[][], isFid;
if (!i) return ;
if (i + deep > maxDeep) return ;
for (i = ; i < ; ++i) {
memcpy(w, preW, sizeof w); memcpy(siz, preSiz, sizeof siz);
for (j = isFid = ; j < n; ++j) {
if (data[j][w[j]] == i) {
isFid = ++w[j]; --siz[j][i];
}
}
if (isFid && DFS(deep + , w, siz)) return ;
}
return ;
}
int main() {
int t, i, j, mp[], w[], siz[][];
mp['A'] = ; mp['C'] = ; mp['G'] = ; mp['T'] = ;
memset(w, , sizeof w);
char str[];
scanf("%d", &t);
while (t--) {
memset(data, , sizeof data); memset(siz, , sizeof siz);
scanf("%d ", &n);
for (i = ; i < n; ++i) {
gets(str);
for (j = ; str[j]; ++j) ++siz[i][data[i][j] = mp[str[j]]];
}
for (maxDeep = vle(siz); !DFS(, w, siz); ++maxDeep);
printf("%d\n", maxDeep);
}
return ;
}