4126:DNA(dfs)

 

总时间限制: 
6000ms
 
内存限制: 
1024kB
描述

考虑一段DNA单链,上面有N个基因片段。这里的基因片段可重叠(例如AGCTC包含AGC和CTC),不可倒置(例如AGCTC不包含TCG)。要问这样的单链最短长度是多少。

输入
输入的第一行是一个正整数T(不超过13),表示数据组数。每组数据若干行,其中第一行一个正整数N(不超过9),表示基因片段的数目,接下来N行每行一个基因片段,由AGCT四个字母组成,且长度介于1和15之间(含两端)。
输出
每组数据输出一样,表示最短的单链长度包含这N个基因片段。
样例输入
1
5
TCGG
GCAG
CCGC
GATC
ATCG
样例输出
11

转自:https://www.cnblogs.com/yalphait/p/9128319.html

 1 //解题思路:
 2 //f[x][y] 表示在x状态下,单链尾的基因片段是 genes[y] 时的最小长度
 3 //x状态的表示方式:主要思想是二进制,我这里设
 4 //的是如果遍历过这个基因片段i,表示状态的二进制数中的第i位(从0算
 5 //起)就变为0(这就是所谓的状态压缩吧)
 6 //然后主要是要把所有包含关系的基因片段剔除,网上搜到一
 7 //个学长的代码其实是不对的,但他提供了一个很好的思路……不过也能A,说明
 8 //数据还是比较弱的……
 9 //WA点:因为我只使用x状态数中的1~n位,在写的时候就要注意把第0位(也就是1
10 //)去掉, f[x][y] 的x范围也要开到 1<<10 ,事实证明是有9个基因片段的数据的。
11 
12 #include <iostream>
13 #include <string.h>
14 #include <algorithm>
15 #include <cstdio>
16 #include <stdlib.h>
17 #include <string>
18 #include <memory>
19 #include <queue>
20 
21 using namespace std;
22 
23 const int maxn = 9;
24 int f[1 << (maxn + 1)][maxn];
25 //x为二进制表示的一维visited状态 y为当前字符串的最后一个基因片段
26 char genes[maxn + 1][20];
27 bool invalid[maxn + 1];
28 int l[maxn + 1];
29 int chong[maxn + 1][maxn + 1];
30 int n, minlen, base;
31 
32 int dp(int state, int last) {
33     if (f[state][last])
34         return f[state][last];
35     f[state][last] = 1 << 10;
36     for (int i = 1; i <= n; i++) {
37         int flag = state & (1 << i);
38         if (invalid[i] && flag != 0) {
39             f[state][last] =min(dp(state - (1 << i), i) + l[last]
40                                 - chong[last][i], f[state][last]);
41         }
42     }
43     return f[state][last];
44 }
45 
46 int main() {
47     int t;
48     scanf("%d", &t);
49     while (t--) {
50         scanf("%d", &n);
51         for (int i = 1; i <= n; i++)
52             cin >> genes[i];
53         memset(f, 0, sizeof(int)*(1 << (maxn+1))*maxn);
54         minlen = 2 << 10;
55         base = 1 << (n + 1);
56         for (int i = 1; i <= n; i++) {
57             invalid[i] = true;
58             f[0][i] = l[i] = strlen(genes[i]);
59         }
60         for (int i = 1; i <= n; i++)
61             for (int j = 1; j <= n; j++) {
62                 if (i != j && invalid[i] && invalid[j] &&
63                         strstr(genes[i], genes[j]) != NULL) {
64                     invalid[j] = false;
65                     base -= 1 << j;
66                 }
67                 if (i != j && invalid[i] && invalid[j]) {
68                     int l0 = min(l[i], l[j]);
69                     while (l0) {
70                         if (strstr(genes[j], genes[i] + l[i] - l0) == genes[j])
71                             break;
72                         l0--;
73                     }
74                     chong[i][j] = l0;
75                 }
76             }
77         for (int i = 1; i <= n; i++)
78             if (invalid[i])
79                 minlen = min(dp(base - (1 << i) - 2, i), minlen);
80         printf("%d\n", minlen);
81     }
82     return 0;
83 }
View Code

 

posted @ 2020-04-03 11:41  瓜瓜爱呱呱  阅读(407)  评论(0编辑  收藏  举报