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.html1 //解题思路: 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 }
越努力越幸运